2011-09-27 127 views
2
public: 
    const int x; 
    base():x(5){} 

}; 

class der : public base { 
public: 
    der():x(10){} 
}; 

der d; 

我的目标是当基类的实例被创建它将初始化x作为5并创建DER类的实例时,它将初始化x作为10.但是编译器是给出错误。 由于x是从类的基类继承的,它为什么会给出错误?初始化基类的常量成员的成派生类

+3

因为'const'意思是不能改变?删除'const'关键字并继续你的生活。 – trojanfoe

+0

我没有改变,我只是将它分配到派生类 – user966379

+0

@trojanfoe:因为Derived类无法在其初始化程序列表中初始化Base属性。 –

回答

4

不能初始化在初始化列表中基类成员在派生类的构造函数。初始化程序列表可以包含基类和此类中的成员,但不包含基数中的成员。

诚然,这样做的standardese并不完全清楚。 12.6.2/2 C++ 03:

除非MEM-初始化ID名称的 构造函数的类的非静态数据成员或该类的直接或虚拟的基础上,所述 MEM-初始化是病态的。

它表示“(构造函数类的非静态数据成员)或(直接或虚拟基)”。它并不意味着“(构造函数类或直接或虚拟基类)的非静态数据成员”。这句话是不明确的,但如果你读了二读,那么你根本就不能把基础放在初始化列表中,而标准中的下一句话则清楚地表明你可以。

至于为什么它不允许的,这是一个标准的合理性问题,我在该标准的作者的动机猜测。但基本上是因为初始化自己的成员是基类的责任,而不是派生类的责任。

也许你应该添加一个int构造函数base

+0

如果允许,成员将被初始化两次,_unless_您引入了一个概念,即派生的ctor init-list **可以覆盖**可访问成员或基类的基本ctor init-list。它会在'base'的情况下破坏封装,因为它打破了一个公共const变量是在声明它的类的ctor中设置的常量的想法。与'virtual'基类初始化相比。 – curiousguy

7

你可以用一个小的调整这项工作...

#include <cassert> 

class base 
{ 
public: 
    const int x; 
    base() 
     :x(5) 
    { 
    } 

protected: 
    base(const int default_x) 
     :x(default_x) 
    { 
    } 
}; 

class der: public base 
{ 
public: 
    der() 
     :base(10) 
    { 
    } 
}; 

struct der2: public base 
{ 
    der2() 
     :base() 
    { 
    } 
}; 

int main() 
{ 
    base b; 
    assert(b.x == 5); 
    der d; 
    assert(d.x == 10); 
    der2 d2; 
    assert(d2.x == 5); 
    return d.x; 
} 

这提供了一个构造函数,由派生类访问,可以提供与初始化base.x默认值。

+0

如果您尝试声明基类型的对象,它不会编译。 –

+1

...因为受保护的构造函数的参数不应具有默认值。有没有好处,因为没有它无论如何将使用无参数构造函数。 –

+0

我在编辑这个内容的同时评论并投票。现在已经修复了。 – Johnsyweb

1

这工作。

class base { 
public: 
    static const int x = 5; 
}; 

class der : public base { 
public: 
    static const int x = 10; 
}; 

如果你想这取决于你的构造改变X,你必须让非静态。

非静态const为相同作为非const变量编译一次。如果你想强制一个成员变量是只读的,使用非静态的const。如果你想设置一个其范围限于一个类的常量,可以使用static const。

+0

为什么const中的类是静态的? –

+0

const必须在类中是静态的才能真正保持不变。 – Pubby

+2

不会。即使没有静电,它也会保持不变。但是对于对象而言,它将是不变的,而不是整个班级(就像静态一样)。 –

0

这可能是过度设计相比原来的问题,但是请注意:

template <typename T, class C, int index=0> 
// C and index just to avoid ambiguity 
class constant_member { 
    const T m; 
    constant_member (T m_) :m(m_) {} 
}; 

class base : virtual public constant_member<int, base> { 
public: 
    base() : constant_member<int, base>(5) {} 
    int x() const { return constant_member<int, base>::m; } 
}; 

class der : public base { 
public: 
    der() : constant_member<int, base>(10) {} 
}; 

class der2 : public der{ 
public: 
    der2() {} // ill-formed: no match for 
       // constant_member<int, base>::constant_member() 
}; 

点评:这是冗长的,非显而易见的(也许无法理解,适合初学者),这将是非常低效的转换为virtual基类只是为了读取一个成员变量。我是而不是真的认为这是一个现实世界的解决方案。

相关问题