2013-03-30 84 views
0

我有兩個班,YX,並且Y持有一些靜態成員 - 這我通過X實例試圖訪問:呼叫從繼承的類的實例靜態成員

template <class T> 
class Y { 
public: 
    Y() { 
     i = 0; 
     v = std::vector<int>(10, 10); 
    } 
    static int value() { 
     return v[i]; 
    } 
private: 
    static int i; 
    static std::vector<int> v; 
}; 

class X : public Y<X> { 
public: 
    X() { 
    } 
}; 

int main() { 
    X *x(new X()); 
    std::cout << x->value() << std::endl; 
} 

即使它編譯,它不正確鏈接:

$ g++ t.cpp 
/tmp/ccB4ijzw.o: In function `Y<X>::Y()': 
t.cpp:(.text._ZN1YI1XEC2Ev[Y<X>::Y()]+0x11): undefined reference to `Y<X>::i' 
t.cpp:(.text._ZN1YI1XEC2Ev[Y<X>::Y()]+0x4a): undefined reference to `Y<X>::v' 
/tmp/ccB4ijzw.o: In function `Y<X>::value()': 
t.cpp:(.text._ZN1YI1XE5valueEv[Y<X>::value()]+0x6): undefined reference to `Y<X>::i' 
t.cpp:(.text._ZN1YI1XE5valueEv[Y<X>::value()]+0x10): undefined reference to `Y<X>::v' 
collect2: ld returned 1 exit status            

上下文(如果它事項):

我想寫一個內存管理器 - class Y - 即靜態持有的內存池,從而使class X使用的內存塊的所有實例的Y提供。

我不確定這是否是我想要做的最好的方法,但是到目前爲止我認爲是最優雅的方式。任何想法都非常受歡迎。

回答

3

靜態數據成員必須定義以及聲明。如果這是一個普通的類,你會做這樣的:

// header: 
class C { 
    static int i; 
}; 

// source: 
int C::i = 3; 

有了類模板,你通常不會把代碼中的源文件,所以你應該這樣做:

// header: 
template <class T> 
class C { 
    static int i; 
}; 

template <class T> 
int C<T>::i = 3; 
+0

啊,就是這樣。我不知道;非常感謝你!還有一個問題。由於我有兩個以上的成員,是否有任何合適的語法允許*多個定義* - 而不是繼續重複'template '?無論如何,它完美的作品! – Rubens

+0

@Rubens - 我不知道。但是,複製和粘貼該行只需要幾個擊鍵。 –

1

由於功能value是靜態的,因此對於class Y的所有實例都是通用的。調用靜態成員函數的方法是一樣

std::cout << Y<X>::value() << std::endl; 

NOT(這是不是非法的,但它僅僅是不是一個好的做法。爲什麼讓功能靜態我你要做到這一點呢?)

std::cout << x->value() << std::endl; 

此外,你必須定義所有的靜態成員。就像

template <class T> 
int Y<T>::i = 0; 

template <class T> 
std::vector<int> Y<T>::v(0); 
+0

我記得看到一個問題,OP詢問是否應該*禁止*通過實例訪問成員,答案表明它不是。 (不管怎樣,我都不會投你的帖子)。 – Rubens

+0

你是什麼意思?我不認爲我理解正確。 – 2013-03-30 20:16:12

+0

通過實例訪問它們並不違法。但是如果你打算這麼做,爲什麼要使這個函數成爲靜態的呢?這是表示它屬於類而不是實例的事​​實。 – 2013-03-30 20:22:18