2017-08-09 29 views
3

我遇到了一个特定的问题,我已将其转换为以下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) {} 

但就是不适合我的情况。

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

+5

号的基类必须完全构造的派生类甚至开始构造之前。你不能只在派生类构造函数体中设置成员? – NathanOliver

+0

@NathanOliver谢谢,不,我不能。父类使用默认参数化来初始化其成员,该默认参数化设置一些网络连接。这些参数在初始化后不能更改。 – jodag

+1

那么如果没有办法设置基类成员,你希望如何设置它? – NathanOliver

回答

4

是它可能推迟父母的成员变量初始化为继承类?如果是这样,怎么样?

父类的成员变量要么在其成员初始化列表中进行初始化,要么在构造函数的主体中进行初始化。子类无法在其初始化程序列表中初始化父类的成员变量 - 这是语言不允许的。你所能做的最好的,似乎是在子类的构造函数的主体中设置父类成员的值。

实施例:

struct foo 
{ 
    int a; 
}; 

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

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

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

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); 
    }; 
}; 
+0

它可能太窄,我可以扩展更多,但问题是关于覆盖父母的初始值设定项。在这个答案中,父母仍然将'Foo'初始化为0,然后Child创建一个值为'1'的'Foo'的新实例并将其复制到'member'。实际上我有点惊讶,因为我认为构造函数初始化的'='形式仅在初始化期间起作用。 – jodag

+0

这是一项任务,而不是初始化。它“工作”,因为'Foo'有一个转换构造函数。 – molbdnilo

+0

为什么你不应该分配给'Parent :: member'变量?如果他们不希望分配给他们,他们会把它变成“私人”的。 –

相关问题