我想在子类而不是基类中初始化常量。并使用它来摆脱动态内存分配(我已经知道数组大小,并且会有一些具有不同常量的子类)。
所以我试试:
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:预期的常量表达式
我怎么能对编译器说它真的是常量?
答案 0 :(得分:4)
虽然不是一个常数。它仍然可以由构造函数修改。对于数组的大小,只允许编译时间常量。当编译器说“常量表达式”时,它并不意味着表达式返回一个常量值,而是一个常量,例如“52”或“45”或沿着这些行的某些东西。
改为使用std::vector
。
编辑:回应“我已经知道数组大小,并且会有一些具有不同常量的子类”
唯一的方法是使用模板。
template<size_t x>
class A {
public:
void f() {
double y[x];
}
};
typedef A<2> B;
答案 1 :(得分: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_;
}
答案 2 :(得分:1)
有“常数”,然后是“常数”。如果你想像这样在堆栈上分配一个数组,编译器需要在编译时获得数组的长度,并且根据你在那里给出的数据,它无法解决这个问题。有趣的是,gcc支持扩展(在标准C ++中不支持),允许为可变长度分配堆栈。
答案 3 :(得分:1)
我不知道它是否适用于您的目的,但一种可能性是将其作为模板参数:
template <int size>
class A {
double y[size];
};
在这种情况下,您可能希望在B中创建A的实例而不是使用继承。
另一个明显的可能性是使用tr1::array
对象。这也是一个模板,所以这个想法几乎相同,但它已经编写,测试和工作,所以你可以避免这一切。如果你的编译器没有提供TR1类,那么Boost有一个最符合要求的实现(boost::array
)。