C ++中的多重继承和默认值

时间:2015-07-22 11:17:30

标签: inheritance c++-cli

我想在对象实例化中使用多重继承来创建一组默认值。

这个概念非常简单,它基于子类定义中父类的顺序。在实例化期间,我希望子项将使用子类定义中使用的LAST父类的默认值完成。

现在我知道我的假设不正确,因为输出结果与预期不同。 C ++编译器返回一个C2385错误说:'成员的模糊访问。

问题:

  1. 我有没有机会对编译器说出我想要的行为或
  2. 如果没有,还有其他的“容易”吗?有机会这样做吗?
  3. 在我的概念中,我想使用自动调度来生成具有一组默认值的对象。我希望C ++编译器能够自己解决冲突,就像在实例化时子类只有一个父类一样。

    在下面的代码中,当Child类被定义为:chn1=3, o1=5值为class Child : public Mother, public Father时,我希望ch值为n1=1, o1=1 Cild类定义如下:class Child : public Father, public Mother

    #include "stdafx.h"
    using namespace System;
    
    class Mother
    {
        public: int n1=1;
        public: int o1=1;
    };
    
    class Father
    {
        public: int n1 = 3;
        public: int o1 = 5;
    };
    
    class Child : public Mother, public Father
    {
        //public: int n1 = 2;
        //public: int o1 = 4;
    };
    
    int main(array<System::String ^> ^args)
    {
    Mother mt = Mother();
    Father ft = Father();
    Child ch = Child();
    
    Console::WriteLine(L"Mother n1: " + mt.n1);
    Console::WriteLine(L"Mother o1: " + mt.o1);
    Console::WriteLine(L"Father n1: " + ft.n1);
    Console::WriteLine(L"Father o1: " + ft.o1);
    Console::WriteLine(L"Child n1: " + ch.n1);
    Console::WriteLine(L"Child o1: " + ch.o1);
    Console::ReadKey();
    return 0;
    }
    

4 个答案:

答案 0 :(得分:3)

成员查找类中名称的规则基本上是:该类具有该名称(在这种情况下查找停止),或者其基类中的一个具有该名称。如果多个基类具有相同的名称,则查找将失败,因为它不明确。

在这种情况下,Child没有名为n1的成员,但它有两个基类(MotherFather) - 所以n1你的意思是暧昧的。

  

在下面的代码中,我希望ch值为n1=3o1=5

这里的基类顺序无关紧要。如果您希望这种情况发生,您需要明确指出您带来的值:

class Child : public Mother, public Father
{
    using Father::n1;
    using Father::o1;
};

现在查找会在n1中找到o1Child,它们将分别为3和5。

答案 1 :(得分:0)

您应该停止重新声明相同的变量名称,从而使先前声明的变量名称变得模糊或无用。我不知道其他语言是如何做到的,但C ++不是他们。

如果你想要&#39;默认&#39;值,只是继承相同的成员变量,但通过构造函数给它们不同的值。派生类可以调用基础构造函数,以便在构造期间传回它们自己的值。

struct Base
{
    int m_number;

    Base(int n): m_number{n} {} // parameterised ctor for Derived, etc.
    Base(): m_number{42} {} // default ctor
};

struct Derived
{
    Derived(): Base{64} {} // override Base default value
};

Base myBase{}; // m_number == 42
Derived myDerived{}; // m_number == 64

等等。

答案 2 :(得分:0)

除了它没有按预期工作(并且一些答案解释了原因)之外,我会质疑你的设计决定是否为你描述的场景使用继承。

相反,你可以使用以下内容:

Interface IValueProvider
{
  int Value1 { get; }
  int Value2 { get; }
}

class Mother : IValueProvider
{
    private: int n1=1;
    private: int o1=1;

    int Value1 { get {return n1;}; }
    int Value2 { get {return n2;}; }
};

// Implement Father similarly to Mother

class Child : IValueProvider
{
    private: List<IValueProvider> valueProviders;

    // Provide a mechanism to populate valueProviders, likely during construction.

    int Value1 { 
       get {
          return valueProviders.Last( v => v.Value1 );
       }; 
    }

    int Value2 { 
       get {
          return valueProviders.Last( v => v.Value2 );
       }; 
    }
};

现在,您可以通过对子项中保存的valueProviders列表中的项进行排序来控制子项返回的值。您还可以对其进行增强,以便在未设置值的情况下,将采用列表中的上一项并返回该值。

为了简洁起见,我使用了C#之类的符号,但你可以用C ++实现这一点。使用和抽象类而不是接口。

答案 3 :(得分:0)

ch此处没有单o1n1,因此它表示模糊访问,它包含MotherFather的子对象。因为你直接使用它

Console::WriteLine(L"Child n1: " + ch.n1);
Console::WriteLine(L"Child o1: " + ch.o1);

编译器无法决定访问哪个n1o1

你可以使用类名来访问它,比如这个

cout << "Child n1: " + ch.Father::n1;

一个建议,请避免使用相同的变量名称。快乐的编码。