我想在对象实例化中使用多重继承来创建一组默认值。
这个概念非常简单,它基于子类定义中父类的顺序。在实例化期间,我希望子项将使用子类定义中使用的LAST父类的默认值完成。
现在我知道我的假设不正确,因为输出结果与预期不同。 C ++编译器返回一个C2385错误说:'成员的模糊访问。
问题:
在我的概念中,我想使用自动调度来生成具有一组默认值的对象。我希望C ++编译器能够自己解决冲突,就像在实例化时子类只有一个父类一样。
在下面的代码中,当Child类被定义为:ch
和n1=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;
}
答案 0 :(得分:3)
成员查找类中名称的规则基本上是:该类具有该名称(在这种情况下查找停止),或者其基类中的一个具有该名称。如果多个基类具有相同的名称,则查找将失败,因为它不明确。
在这种情况下,Child
没有名为n1
的成员,但它有两个基类(Mother
和Father
) - 所以n1
你的意思是暧昧的。
在下面的代码中,我希望ch值为
n1=3
,o1=5
这里的基类顺序无关紧要。如果您希望这种情况发生,您需要明确指出您带来的值:
class Child : public Mother, public Father
{
using Father::n1;
using Father::o1;
};
现在查找会在n1
中找到o1
和Child
,它们将分别为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
此处没有单o1
和n1
,因此它表示模糊访问,它包含Mother
和Father
的子对象。因为你直接使用它
Console::WriteLine(L"Child n1: " + ch.n1);
Console::WriteLine(L"Child o1: " + ch.o1);
编译器无法决定访问哪个n1
和o1
。
你可以使用类名来访问它,比如这个
cout << "Child n1: " + ch.Father::n1;
一个建议,请避免使用相同的变量名称。快乐的编码。