基类作为c ++中派生类构造函数的参数

时间:2014-12-08 18:21:02

标签: c++ inheritance

我在派生类中遇到构造函数问题。假设我在下面有一个简单的代码,其中包含一个基类Base和两个继承自Base,Derived1和Derived2的类。

我希望Derived2持有指向Base的指针,它可以指向Base或Derived1。我无法为此编写构造函数。如果我传入Derived1对象,我会在构造函数中获得一个空Base。

Class Base
{
public:
      Base(int a): m_a(a)
      {
      }

protected:
         int m_a;
};


//First derived class of base
class Derived1 : public Base
{
public:
        Derived1(double c): m_c(c)
        {
        }

private:
        double m_c;
};


//Second derived class of Base
class Derived2 : public Base
{
public:
        Derived2(Base b, int k): m_b(&b), m_k(k)
        {
        }

private:
        int m_k;
        Base* m_b;
};


int main()
{
    Base b(2);
    Derived1 d1(3.0);


    Derived2 d2(d1, 3);
    Derived2 d3(b, 4);
}

3 个答案:

答案 0 :(得分:0)

您可能希望在构造函数中接受Base*,而不是实际的Base实例:

Derived2(Base* b, int k) : m_b(b), m_k(k)
{
}

然后,您可以传递您希望Derived2实例指向的实例的地址:

Derived2 d2(&d1, 3);
Derived2 d3(&b, 4);

请注意,您应该考虑Base实例中指向的Derived2对象的所有权。此外,如果在删除传递的Derived2对象后Base对象仍然存在,则访问m_b将导致未定义的行为。如果您可以使用C ++ 11,请考虑传递和存储std::shared_ptr<Base>而不是原始指针。

答案 1 :(得分:0)

我理解您希望Derived2持有指向另一个Base对象的指针。

第一个问题:您的构造函数使用基础对象的值参数:

    Derived2(Base b, int k): m_b(&b), m_k(k)

这意味着当它被调用时,会为b传递参数的临时副本,并且您将存储此临时对象的地址。当然,一旦你离开调用构造函数的语句,这个地址就会失效。 Segfault迟早会保证!

解决方案: 按引用传递参数(其余代码未更改):

    Derived2(Base& b, int k): m_b(&b), m_k(k)

第二个问题:您的代码无法编译,因为Base没有默认构造函数,Derived1Derived2的构造函数不提供对于初始化列表中的有效Base

解决方案1: 在所有派生构造函数中提供显式的基本初始化。例如:

    Derived2(Base& b, int k) : m_b(&b), m_k(k), Base(k)  // is k the right value ? 
    { ... }

解决方案2: 或者考虑使用Base构造函数参数的默认值:

    Base(int a=0): m_a(a)  // default parameter is 0 
    { ... }

答案 2 :(得分:0)

这里有很多问题。让我们暂时忽略Derived2的设计问题(裸指针是邪恶的)。

专注于Derived1 ...

Derived1派生自Base,这意味着 Base。 Base只有一个参数构造函数(因此没有默认构造函数)

Derived1也有一个1参数构造函数,但是这个参数正在初始化Derived1的数据(m_c)。

由于Derived Base,因此必须在构建时构建它的Base部分。既然你必须构造Base,而base只有一个1参数的构造函数,你必须在Derived1的构造函数中特别提到它。

像这样:

class Derived1 : public Base
{
public:
    Derived1(double c, int some_value_for_base)
    : Base(some_value_for_base)
    , m_c(c)
    {
    }

...
};