2009-05-19 100 views
0

誰能向我解釋爲什麼以下工作:爲什麼這個C++類不等同於這個模板?

template<class T> class MyTemplateClass { 
public: 
    T * ptr; 
}; 

int main(int argc, char** argv) { 
    MyTemplateClass<double[5]> a; 
    a.ptr = new double[10][5]; 
    a.ptr[2][3] = 7; 
    printf("%g\n", a.ptr[2][3]); 
    return 0; 
} 

但這並不:

class MyClass { 
public: 
    double[5] * ptr; 
    // double(*ptr)[5]; // This would work 
}; 

int main(int argc, char** argv) { 
    MyClass a; 
    a.ptr = new double[10][5]; 
    a.ptr[2][3] = 7; 
    printf("%g\n", a.ptr[2][3]); 
    return 0; 
} 

顯然,不僅僅是文本替換由參數模板更多的模板實例 - 這個魔術有簡單的解釋嗎?

對於後者的編譯器(克++ 4.1.2)吐出以下錯誤:

test.cxx:13: error: expected unqualified-id before '[' token 

其中線13是double[5] * ptr;線。

的問題不是:

「爲什麼MyClass的例子失敗 - 因爲C++不允許的Java風格的數組聲明;-)?」。

但就是:

「爲什麼MyTemplateClass例如成功嗎?」

+0

編譯器是否吐出任何錯誤消息? – Tom 2009-05-19 16:15:02

回答

9

區別在於C++語法。一個簡單的聲明是這樣形成:

declaration-specifier-seq init-declarator-list 

哪裏聲明說明符-SEQ是聲明說明符的序列:

simple-type-specifier: int, bool, unsigned, typedef-name, class-name ... 
class-specifiers: class X { ... } 
type-qualifier: const, volatile 
function-specifier: inline, virtual, ... 
storage-class-specifier: extern, static, ... 
typedef 

你的想法。和init聲明符列表是聲明符爲每個可選的初始化列表:

a 
*a 
a[N] 
a() 
&a = someObj 

所以,一個完整的簡單的聲明看起來是這樣的,含有3說明符:

int a, &b = a, c[3] = { 1, 2, 3 }; 

類成員特殊規則來說明它們出現的不同背景,但它們非常相似。現在,你可以做

typedef int A[3]; 
A *a; 

因爲首先使用的typedef符,然後簡單類型說明符,然後像「一個[N]」說明符。然後第二個聲明使用typedef名稱「A」(簡單類型說明符),然後使用「* a」之類的聲明符。但是,當然不能做

int[3] * a; 

由於「INT [3]」不是有效的聲明說明符-SEQ如上所示。

而現在,當然,模板是就像宏文本替換。當然,模板類型參數的處理方式與任何其他類型名稱一樣,只能解釋爲它所命名的類型,並且可以出現在簡單類型說明符可以出現的位置。一些C#人傾向於說C++模板「就像宏」,但當然不是:)

3
template<class T> MyTemplateClass { 
    ... 
} 

更接近

template<class T> MyTemplateClass { 
    typedef {actual type} T; 
    ... 
} 

比簡單的文本替換。

0

使用指針或指針數組有區別。在打算使用它之前,需要爲陣列的每個元素分配內存,並且是在第二個示例中沒有定義模板的情況下有錯字。