2010-06-16 108 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)。