简体   繁体   English

将基类的const成员初始化为派生类

[英]initialisation of const member of base class into derive class

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

};

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

der d;

My aim is when instance of base class is created it will initialise x as 5 and when instance of der class is created it will initialise x as 10. But compiler is giving error. 我的目标是当创建基类的实例时,它将x初始化为5,当创建类的实例时,它将x初始化为10.但编译器给出了错误。 As x is inherited from class base, why is it giving error? 由于x是从类库继承的,为什么它会给出错误?

You can make this work with a little adjustment... 你可以通过一点调整来完成这项工作......

#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;
}

This provides a constructor, accessible by derived classes, that can provide a default value with which to initialise base.x . 这提供了一个可由派生类访问的构造函数,它可以提供用于初始化base.x的默认值。

You can't initialize a base class member in the initializer list for a constructor in the derived class. 您无法在派生类中的构造函数的初始值设定项列表中初始化基类成员。 The initializer list can contain bases, and members in this class, but not members in bases. 初始化列表可以包含此类中的基础和成员,但不包含基础中的成员。

Admittedly, the standardese for this isn't entirely clear. 不可否认,这方面的标准并不完全清楚。 12.6.2/2 of C++03: C ++ 03的12.6.2 / 2:

Unless the mem-initializer-id names a nonstatic data member of the constructor's class or a direct or virtual base of that class, the mem-initializer is ill-formed. 除非mem-initializer-id命名构造函数类的非静态数据成员或该类的直接或虚拟基础,否则mem-initializer是不正确的。

It means "(a nonstatic data member of the constructor's class) or (a direct or virtual base)". 它的意思是“(构造函数类的非静态数据成员)或(直接或虚拟基础)”。 It doesn't mean "a nonstatic data member of (the constructor's class or a direct or virtual base)". 它并不意味着“(构造函数的类或直接或虚拟基础)的非静态数据成员”。 The sentence is ambiguous, but if you took the second reading then you couldn't put bases in the initializer-list at all, and the very next sentence in the standard makes it clear that you can. 这个句子含糊不清,但是如果你读了二读,你根本就不能在初始化列表中放置基数,而标准中的下一个句子清楚表明你可以。

As for why it's not allowed, that's a standard rationale question and I'm guessing at the motives of the authors of the standard. 至于为什么不允许,这是一个标准的理由问题,我猜测标准作者的动机。 But basically because it's the base class's responsibility to initialize its own members, not the derived class's responsibility. 但基本上是因为基类有责任初始化自己的成员,而不是派生类的责任。

Probably you should add an int constructor to base . 可能你应该添加一个int构造函数到base

This works. 这有效。

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

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

If you want to change x depending on your constructor, you have to make it non-static. 如果要根据构造函数更改x,则必须使其为非静态。

A non-static const is the same as a non-const variable once compiled. 一旦编译,非静态const与非const变量相同。 If you want to enforce a member variable to be read-only, use non-static const. 如果要将成员变量强制为只读,请使用非静态const。 If you want to set a constant whose scope is restricted to a single class, use static const. 如果要设置其范围仅限于单个类的常量,请使用static const。

This may be over-engineered compared the original question, but please consider: 与原始问题相比,这可能过度设计,但请考虑:

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() 
};

Comment: This is verbose, non-obvious (maybe impossible to understand for beginners), and it will be very inefficient to convert to virtual base class just to read a member variable. 评论:这是冗长的,非显而易见的(对初学者来说可能无法理解),转换为virtual基类只是为了读取成员变量是非常低效的。 I am not really suggesting this as a real world solution. 并不是真的建议这是一个真实的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C ++初始化:const全局与静态类成员的顺序 - C++ initialisation: order of const global vs static class member 是constexpr从中间派生类引用访问基类成员吗? - Is it constexpr accessing base class member from intermediate derive class reference? 在基类/派生类的成员函数/好友函数中派生*到Base *的转换 - Derive* to Base* conversion in member function/friend function of base/derived class 类成员初始化差异 - Class member initialisation differences 类实例成员初始化 - class instance member initialisation 在大多数派生类中初始化基类const成员 - Initializing base class const member in most derived class 如何延迟C ++基类中成员的初始化,直到派生类的ctor被执行? - How to delay the initialisation of a member in a C++ base class until the ctor of derived class is executed? 如果基类和派生类具有相同的成员变量,编译器如何解析要调用哪个成员? - If both base and derive class has a same member variable, how compiler resolve which member is to be called? 在创建派生类对象时初始化基类成员的更好方法是哪种? - Which is the better approach to initialise the base class member while creating derive class object? 将类初始化的const成员传递给Base构造函数? - Pass in-class initialized const member to Base constructor?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM