是否可以将成员变量初始化推迟到继承类而不修改父类?

时间:2017-08-09 19:06:48

标签: c++ class inheritance initialization

我遇到了一个特定问题,我已将其转换为以下Minimal, Complete, and Verifiable example

#include <iostream>

class Foo {
    public:
        Foo(int v) : val(v) {}

        int get_val() const
        {
            return val;
        }

    private:
        int val;
};

class Parent {
    public:
        Parent() : member(0) {}

        const Foo& get_member() const
        {
            return member;
        }

    protected:
        Foo member;
};

// Nothing above this line should be changed

class Child : public Parent
{
    public:
        // This doesn't work (compile error)
        //Child() Parent::member(1) {}

        // Nor does this (also a compile error)
        //Child() this->member(1) {}
};

int main()
{
    Child x;
    std::cout << x.get_member().get_val() << std::endl;
    return 0;
}

这个例子演示了我在一个更大的软件项目中遇到的问题,我从一个外部库继承但是需要直接初始化一个父成员变量

不幸的是,Parent类没有一个构造函数来参数化其成员的初始化。

如果Parent类有一个

形式的构造函数
Parent(int val) : member(val) {}

然后我可以将Child构造函数写为

Child() Parent::Parent(1) {}

但对我来说情况并非如此。

问题:是否可以将父成员变量的初始化推迟到继承的类?如果是这样,怎么样?

2 个答案:

答案 0 :(得分:4)

  

是否可以将父成员变量的初始化推迟到继承的类?如果是这样,怎么样?

父类的成员变量在其成员初始化列表或构造函数体中初始化。子类无法在其初始化列表中初始化父类的成员变量 - 该语言不允许这样做。看来,您可以做的最好的事情是在子类的构造函数的主体中设置父类的成员的值。

示例:

struct foo
{
   int a;
};

struct bar : foo
{
   bar() : a(0) {} // Not allowed
};

struct bar : foo
{
   bar() { a = 0; } // Allowed
};

答案 1 :(得分:1)

最简单的方法是在Parent::member类构造函数体中再次初始化Child

class Child : public Parent
{
    public:
        Child() {
            Parent::member = 1;
        }

};

请参阅live demo

正如评论中澄清的那样,你不应该分配 Parent::member变量。

在这种情况下(让我们假设设计至少是有用的), 您通常可以为父类成员的实例的某些属性应用setter:

class Foo {
    Foo(const& Foo) = delete;
    Foo& operator=(const& Foo) = delete;
public:
    Foo() = default;
    int property() const;
    void property(int newVal);
};

class Parent {
protected:
    Foo member;
public:
    Parent() = default;
};

class Child : public Parent {
public:
    Child() {
        Parent::member.property(1);
    };
};