2010-06-16 92 views
3

我想初始化子類中的常量,而不是基類。並用它來擺脫動態內存分配(我已經知道數組大小,並且會有一些具有不同常量的子類)。
所以我嘗試:C++初始化常量和繼承

class A { 
public: 
    const int x; 

    A() : x(0) {} 
    A(int x) : x(x) {} 
    void f() { 
     double y[this->x]; 
    } 
}; 

class B : A { 
    B() : A(2) {} 
}; 

很簡單,但是編譯器說:

錯誤C2057:預期常量表達式

我怎麼能告訴編譯器,它是一個真正的不變?

+2

如果它的值是在運行時確定的,那麼它不是一個常量表達式。這樣考慮:常量表達式是常量,這意味着數組的大小在所有A中都是恆定的。然而,你需要A的不同尺碼。不同的大小 - >不是恆定的。 – GManNickG 2010-06-16 23:17:26

回答

4

雖然這不是一個常數。它仍然可以通過構造函數進行修改。數組大小隻允許編譯時間常量。當編譯器說「常量表達式」時,它不是一個表達式,它返回一個常量值,而是一個常數,例如「52」或「45」等等。

改爲使用std::vector

編輯:在回答「我知道數組的大小已經,而且會有一些兒童類具有不同的常數」

做到這一點的唯一方法是使用模板。

template<size_t x> 
class A { 
public: 
    void f() { 
     double y[x]; 
    } 
}; 

typedef A<2> B; 
2

您期望的行爲可以使用以下模板來實現。

請注意,這實際上是不可靠的,噁心的,可以只用作「樣本」。改爲使用std::vector

template <size_t a = 0> 
class A { 
public: 
    A() { } 

    void f() { 
     int y[a]; 
     y[0] = 5; 
    } 
}; 

class B : A<2> { 
    B() { } 
}; 

void main() { 
    A<1> a; 
    a.f(); 

    // Undefined behaviour - creating an array of size 0 
    // At least, MSVS2008 treats it as an error :) 
    // A<0> a_; 
} 
+0

Gah;毆打我的四秒鐘! – strager 2010-06-16 23:21:11

+0

不確定允許負值是一個好主意。 (使用像size_t這樣的無符號整數類型,不是int) – 2010-06-16 23:21:22

+1

'//錯誤在這裏!'是否會導致錯誤?如果有的話,在'y [0] = 5;'處只是未定義的行爲。 – strager 2010-06-16 23:22:17

1

有 「不變」,然後有 「不變」。如果你想像這樣在堆棧上分配一個數組,編譯器在編譯時需要這個數組的長度,並且根據你在那裏給出的數據,它無法弄清楚。有趣的是,gcc支持一個擴展(在標準C++中不支持),允許爲不同長度的堆棧分配。

+0

GCC支持這個的原因是C++沒有重複C99的功能。 C++ 0x沒有添加該功能,因爲C++有'vector',使得可變長度數組nill的效用。 – 2010-06-16 23:24:20

1

我不知道這是否符合您的需求,但一個可能的方法是使它成爲一個模板參數:

template <int size> 
class A { 
    double y[size]; 
}; 

在這種情況下,你可能想要創建一個實例在B中而不是使用繼承。

另一個顯而易見的可能性是使用tr1::array對象。這也是一個模板,所以這個想法幾乎是一樣的,但它已經被編寫,測試和工作,所以你可以避免所有這些。如果你的編譯器不提供TR1類,Boost有一個主要符合實現(boost::array)。