Shell's Home

Feb 2, 2007 - 1 minute read - Comments

继承类静态对象虚拟化

其实这个标题不准确,准确的说,应该是继承类拥有自己的基类静态对象。

我们知道,类中的静态对象本质上是全局变量,不过名字在类命名空间里面。如果类B有静态对象S,D继承了B(先按照public继承讨论,其他其实也一样)。那么在D里面访问S的时候,其实是访问的B命名空间里面的静态对象S。验证代码如下:

class B {
protected:
    static int S;
};

int B::S = 0;

class D:public B {
public:
    void print () {
        printf ("%dn", S);
    };
};

class E:public B {
public:
    static void rewrite () {
        S = 1;
    };
};

int _tmain (int argc, _TCHAR * argv[]){
    D d;
    d.print ();
    E::rewrite ();
    d.print ();
    return 0;
}

上例中可以看到,两个继承类,其实都是将父类的命名空间导入而已。假定我们要使得每类专有一个静态成员,例如我们要计算每个类的生成对象个数,怎么办呢?

如果不用继承,我们可以在每个类里面加一个静态成员。然后在构造函数中加1,析构中减1。但是如果我们想把这个功能放到基类中,事情就麻烦了。因为所有类从同一个基类派生,我们算出来的其实是所有从基类继承的类的总对象生成个数。

当然,我们可以用实现的方法来做。把所需要的功能抽离出来,放到一个单独的计数类中。然后构造的时候调用加1,析构的时候减1。听起来很蠢,那是因为例子容易的关系。比较复杂的时候,这样抽象相对简单的。计数类可以用于多个类,实现了代码重用。但是仍旧没有解决关键问题,怎么让继承类特化基类的静态对象?(虚拟化和特化的意思差不多,就是针对具体对象使用具体方法)

答案最后被我在More Effective C++中找到了,正确的方法不是寻找一个特化的方法,而是继承不同的基类,使用同一套代码。既然是不同基类,怎么具备同一套代码呢?想到了吧,模版。

template<T>
class B {
protected:
    static int S;
};

class D:public B<D> {
public:
    void print () {
        printf ("%dn", S);
    };
};

int B<D>::S = 0;

class E:public B<E> {
public:
    static void rewrite () {
        S = 1;
    };
};

int B<E>::S = 0;

int _tmain (int argc, _TCHAR * argv[])
{
    D d;
    d.print ();
    E::rewrite ();
    d.print ();
    return 0;
}

看到了?每个继承类拥有了自己的静态成员。如果我们把上面的例子中,S改成ID。就可以做到RTTI了(只是还需要很多技巧)。

Tags: c oo program

轻轨意外延迟的处理过程 CPUID

comments powered by Disqus