这个C ++代码的安全性和编译器独立性如何?

时间:2015-01-08 00:24:44

标签: c++ templates inheritance static virtual-functions

我创建了一些对我来说很奇怪的代码,但似乎做了我想要的。但是,我不确定它的平台独立性或它的安全性,或者是否有更简单的方法来做我想要的事情。

我正在阅读奇怪的重复模板程序(on wikipedia),并且有一个类计数器的示例代码,它允许每个派生类通过从基础继承来跟踪已创建的实例数。功能。

我一直在寻找让派生类引用公共对象(通过指针)的方法,而不必添加静态变量并为我创建的每个新类定义虚函数。 (我正在计划创建相当多的派生类。)但是,派生类因为它们是使用模板创建的,因此被认为与基础不同,因此无法将它们隐式转换为基本指针。

Dynamic_cast和static_cast不起作用,所以我尝试了reinterpret_cast,以获得乐趣,看看有什么行为。它最终显示了基类中的静态变量,这不是我想要的,但它让我想起了之前我对静态和虚函数的经验(长篇故事)。我在基类中编写了一个虚函数,虚函数报告了派生类的正确变量,多态。

它起作用,至少根据codepad.org,但我仍然不确定它的平台一致性或在这种情况下reinterpret_cast的安全性。有经验的人可以说清楚为什么会有效吗?

这是我的代码。它看起来像维基百科的示例代码,因为它就是它原来的样子。

#include <iostream>
using namespace std;

template <typename T>
class counter
{
    public:
    static int separateObject;
    virtual void printStatic(){
    cout << this->separateObject << endl;
    }
};

template <typename T> int counter<T>::separateObject( 0 );

class X : public counter<X>
{
    // ...
};

class Y : public counter<Y>
{
    // ...
};

typedef counter<void*>* voidcounter;
int main(){
    X* counterX = new X;
    Y* counterY = new Y;
    counterX->separateObject = 9001;
    counterY->separateObject = 42;
    cout << "Object Xs value is: " << counterX->separateObject << endl;
    cout << "Object Ys value is: " << counterY->separateObject << endl;
    voidcounter polycount = reinterpret_cast<voidcounter>(counterX);
    polycount->printStatic();
    polycount = reinterpret_cast<voidcounter>(counterY);
    polycount->printStatic();
    return 0;
}

1 个答案:

答案 0 :(得分:1)

  

我一直在寻找让派生类引用公共对象的方法

然后不要使用CRTP。 CRTP适用于您需要所有基类型不常见的情况(这是允许每种类型拥有它自己的计数器的原因)。这完全是它的100%。如果需要共享公共库,请使用普通的虚拟基类。您无法使用static_castdynamic_cast,因为它们没有共同基础。您使用reinterpret_cast所做的事情是非常不安全的,因为它是未定义的行为。

class shared_counter_base {
    virtual ~shared_counter_base(){}
    virtual void printStatic()=0;
};

template <typename T>
class counter : shared_counter_base 
{
    public:
    static int separateObject;
    virtual void printStatic() {
    cout << this->separateObject << endl;
    }
};

template <typename T> int counter<T>::separateObject( 0 );

class X : public counter<X>
{
    // ...
};

class Y : public counter<Y>
{
    // ...
};

int main(){
    X* counterX = new X;
    Y* counterY = new Y;
    counterX->separateObject = 9001;
    counterY->separateObject = 42;
    cout << "Object Xs value is: " << counterX->separateObject << endl;
    cout << "Object Ys value is: " << counterY->separateObject << endl;
    shared_counter_base  polycount = counterX;
    polycount->printStatic();
    polycount = counterY;
    polycount->printStatic();
    return 0;
}