初始化基类的常量成员的成派生类
public:
const int x;
base():x(5){}
};
class der : public base {
public:
der():x(10){}
};
der d;
我的目标是当基类的实例被创建它将初始化x作为5并创建DER类的实例时,它将初始化x作为10.但是编译器是给出错误。 由于x是从类的基类继承的,它为什么会给出错误?初始化基类的常量成员的成派生类
不能初始化在初始化列表中基类成员在派生类的构造函数。初始化程序列表可以包含基类和此类中的成员,但不包含基数中的成员。
诚然,这样做的standardese并不完全清楚。 12.6.2/2 C++ 03:
除非MEM-初始化ID名称的 构造函数的类的非静态数据成员或该类的直接或虚拟的基础上,所述 MEM-初始化是病态的。
它表示“(构造函数类的非静态数据成员)或(直接或虚拟基)”。它并不意味着“(构造函数类或直接或虚拟基类)的非静态数据成员”。这句话是不明确的,但如果你读了二读,那么你根本就不能把基础放在初始化列表中,而标准中的下一句话则清楚地表明你可以。
至于为什么它不允许的,这是一个标准的合理性问题,我在该标准的作者的动机猜测。但基本上是因为初始化自己的成员是基类的责任,而不是派生类的责任。
也许你应该添加一个int
构造函数base
。
如果允许,成员将被初始化两次,_unless_您引入了一个概念,即派生的ctor init-list **可以覆盖**可访问成员或基类的基本ctor init-list。它会在'base'的情况下破坏封装,因为它打破了一个公共const变量是在声明它的类的ctor中设置的常量的想法。与'virtual'基类初始化相比。 – curiousguy
你可以用一个小的调整这项工作...
#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
默认值。
如果您尝试声明基类型的对象,它不会编译。 –
...因为受保护的构造函数的参数不应具有默认值。有没有好处,因为没有它无论如何将使用无参数构造函数。 –
我在编辑这个内容的同时评论并投票。现在已经修复了。 – Johnsyweb
这工作。
class base {
public:
static const int x = 5;
};
class der : public base {
public:
static const int x = 10;
};
如果你想这取决于你的构造改变X,你必须让非静态。
非静态const为相同作为非const变量编译一次。如果你想强制一个成员变量是只读的,使用非静态的const。如果你想设置一个其范围限于一个类的常量,可以使用static const。
为什么const中的类是静态的? –
const必须在类中是静态的才能真正保持不变。 – Pubby
不会。即使没有静电,它也会保持不变。但是对于对象而言,它将是不变的,而不是整个班级(就像静态一样)。 –
这可能是过度设计相比原来的问题,但是请注意:
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
基类只是为了读取一个成员变量。我是而不是真的认为这是一个现实世界的解决方案。
因为'const'意思是不能改变?删除'const'关键字并继续你的生活。 – trojanfoe
我没有改变,我只是将它分配到派生类 – user966379
@trojanfoe:因为Derived类无法在其初始化程序列表中初始化Base属性。 –