2015-01-08 54 views
0

我已经创建了一些对我来说很陌生的代码,但似乎按照我的意愿去做。但是,我不确定它的平台独立性或它的安全性,或者是否有更简单的方法来实现我想要的功能。这个C++代码如何安全且独立于编译器?

我正在阅读Curiously Recurring Template Program(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; 
} 
+0

为什么不'struct interface {virtual void printStatic()= 0; };模板结构计数器:接口{静态int separateObject; void printStatic()override {cout << separateObject << endl; }};'? – dyp

+0

@BillLynch对不起,关于外部链接,我是StackOverFlow的新手。 – gajbooks

+0

@dyp这是做到这一点的一种方法,但我想避免在我的代码的情况下从“counter”派生的每个类中重新定义一个函数,而在您的示例的情况下,我需要“interface”。 – gajbooks

回答

1

我一直在寻找各种方法来有派生类,对于共同目标

那么就不要使用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; 
} 
+0

如果有的话,我会放弃这个方法,因为'reinterpret_cast'是不安全的。我不确定编译器是否为每个派生类生成了不同的代码,尽管没有使用模板相关成员。 – gajbooks

+0

@gajbooks:他们当然可以,这就是CTRP存在的全部原因。 –