翻译:C++的内部类机制

Alex posted @ 2012年5月09日 13:09 in C/CPP , 1024 阅读

节选自:Thinking in C++ Vol. 2 - Practical Programming

http://www.linuxtopia.org/online_books/programming_books/c++_practical_programming/c++_practical_programming_254.html

……我们从Java借用来一种解决方案,在C++的内嵌类的基础上向前进一步。Java中内置了内部类Inner Class)的机制,与C++中的内嵌类(nested class)相似,但却能够能访问外围类的非静态成员,因为它可以隐含地使用其创建者(外围类的一个实例)的this的指针。

如果要在C++中实现内部类,我们就必需显式地获得和使用外围类对象的指针。以下为示例:

//: C10:InnerClassIdiom.cpp

// Example of the "inner class" idiom.

#include
#include
using namespace std;
class Poingable {
public:
    virtual void poing() = 0;
};

void callPoing(Poingable& p) {
    p.poing();
}

class Bingable {
public:
    virtual void bing() = 0;
};

void callBing(Bingable& b) {
    b.bing();
}

class Outer {

    string name;
    // Define one inner class:
    class Inner1;
    friend class Outer::Inner1;
    class Inner1 : public Poingable {
        Outer* parent;
    public:
        Inner1(Outer* p) : parent(p) {}
        void poing() {
            cout << "poing called for "
            << parent->name << endl;
            // Accesses data in the outer class object
        }
    } inner1;
    // Define a second inner class:
    class Inner2;
    friend class Outer::Inner2;
    class Inner2 : public Bingable {
        Outer* parent;
    public:
        Inner2(Outer* p) : parent(p) {}
        void bing() {
            cout << "bing called for "
            << parent->name << endl;
        }
    } inner2;

public:
    Outer(const string& nm)
    : name(nm), inner1(this), inner2(this) {}
    // Return reference to interfaces
    // implemented by the inner classes:
    operator Poingable&() { return inner1; }
    operator Bingable&() { return inner2; }

};

int main() {
    Outer x("Ping Pong");
    // Like upcasting to multiple base types!:
    callPoing(x);
    callBing(x);

} ///:~

 

上面这个例子有意使用了最简单的语法来说明这个机制(以后能看到一个实际的应用)。从PoingableBingable接口定义开始,它们各有一个成员函数。由callPoing( )callBing( )提供的服务仅要求所传入的对象分别具备PoingableBingable接口,以最大限度地保持这两个函数的灵活性。请注意两个接口都没有虚拟的析构函数,目的是防止通过接口进行析构。

 

Outer构造器中包含了一些私有数据(name),我们希望它同时提供Poingable接口和Bingable接口以便能够在callPoing( )callBing( )中使用它。(这里当然我们完全可以简单地使用多重继承,但这只是个为了说明而有意简化过的例子)。为了让Outer类在不继承Poingable的情况下提供Poingable接口,我们使用了内部类机制。

 

首先,class Inner的声明指出我们在其他地方以这个名字定义了内嵌类,这样接下来就可以将这个内嵌类定义为友元,以便在内嵌类中可以自由地访问外部类的成员。然后,我们就可以定义内嵌类了,注意它保存了创建者的指针(Outer类),并在构造函数中初始化了这个指针。最后,我们实现了Poingablepoing( ) 函数。对另一个实现Bingable接口的内部类,流程是一样的。两个内部类都只创建了一个私有实例,由Outer构造器完成初始化。创建成员对象后,返回的是对它们的引用这样对象生存期的问题就被解决了。

 

请注意,两个内部类的定义都是私有的,实际上客户端代码根本访问不到其具体实现,因为访问函数operator Poingable&( )operator Bingable&( )返回的是基类的引用,而不是对实例的引用。事实上,由于两个内部类都是私有的, 客户端程序甚至无法将该引用向下转换到实现类,这样,接口和实现之间就实现了完全隔离。

 

定义自动的类型转换函数operator Poingable&( )operator Bingable&( )使整个机制能更加灵活。在main( )中可以看到,语法上仿佛Outer 是从 PoingableBingable多重继承而来,但区别在于,这种转换是单向的,可以向上转换为 PoingableBingable,却不能向下转回Outer

来自:http://linwx1978.blog.163.com/blog/static/1504106920099145846111/


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter