这段 C++ 代码的安全性和独立于编译器的程度如何?

How safe and compiler-independent is this C++ code?

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

我正在阅读 Curiously Recurring Template Program (on wikipedia),其中有一个 class 计数器的示例代码,它让每个派生的 class 跟踪有多少实例已经通过从具有该功能的基础继承而创建。

我一直在寻找方法来导出 classes 对公共对象的引用(通过指针),而不必添加静态变量并为每个新 class 定义虚函数我创造。 (我计划创建很多派生的 classes。)但是,派生的 classes,因为它们是用模板创建的,被认为与基础不同,所以它们不能隐式转换为一个基指针。

Dynamic_cast 和 static_cast 没有用,所以我尝试了 reinterpret_cast,为了好玩,看看有什么行为。它最终显示了基 class 中的静态变量,这不是我想要的,但它让我想起了我以前在静态和虚函数方面的经验(长话短说)。我在基础 class 中写了一个虚函数,虚函数为派生的 classes 报告了正确的变量,多态性盟友。

它有效,至少根据 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;
}

I had been looking for ways to have derived classes reference to a common object

那就别用CRTP了。 CRTP 适用于当您需要所有基本类型不通用时(这允许每种类型都有自己的计数器)。这 100% 正是它的用途。如果你想要一个共享的公共基础,使用一个普通的虚拟基础class。您不能使用 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;
}