2015-01-08 88 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存在的全部原因。 –