C++ C++;如何初始化抽象基类引用元素?
我的问题基于典型的菱形层次结构,但不是典型的菱形问题C++ C++;如何初始化抽象基类引用元素?,c++,inheritance,virtual-inheritance,diamond-problem,C++,Inheritance,Virtual Inheritance,Diamond Problem,我的问题基于典型的菱形层次结构,但不是典型的菱形问题 class Interface { public: int value; // SomeBigData &data; Interface(int _value = 0) : value(_value) {}; virtual void function1() = 0; virtual void function2() = 0; }; class ImpOne : public vi
class Interface
{
public:
int value;
// SomeBigData &data;
Interface(int _value = 0) : value(_value) {};
virtual void function1() = 0;
virtual void function2() = 0;
};
class ImpOne : public virtual Interface
{
public:
void function1() { ++value; }
};
class ImpTwo : public virtual Interface
{
public:
void function2() { --value; }
};
class Device : public ImpOne, public ImpTwo
{
public:
Device() : Interface(7) {};
};
有一个抽象接口定义了许多函数(上面的示例已简化)。还有一些实现类,它们一次只实现其中的几个函数。最后,还有一个非抽象类,如上面的类设备,通过将几个实现类组合在一起来实现整个接口
现在,问题是:
接口类中有一个整数元素,它由类设备初始化,并在实现类之间共享,到目前为止还不错。但是如果我从接口(int\u value=0)
构造函数中删除=0
,整个系统将崩溃,因为我缺少接口类的默认构造函数,这有点奇怪,因为它从未被调用
为什么这会困扰我?正如代码中所建议的,接口类需要包含对复杂数据结构(不属于类)的引用,而这些数据结构是在所有派生实现类之间共享的。但是,为引用指定默认值既不合理也不可能
因此,问题是:
如何正确初始化代码中建议的接口类(引用)元素,例如SomeBigData&data
,其中我不能为默认构造函数指定默认值(无论如何都不会调用它)?还是我做错了什么 您可以这样做:
class Interface {
public:
int value;
virtual SomeBigData& getBigData() = 0;
Interface(int _value = 0) : value(_value) {};
virtual void function1() = 0;
virtual void function2() = 0;
};
class BigDataProvider : public virtual Interface {
public:
SomeBigData& data_;
BigDataProvider(SomeBigData& data) : data_(data) {}
SomeBigData& getBigData() { return data_; }
};
class Device : public BigDataProvider, public ImpOne, public ImpTwo {
public:
Device(SomeBigData& data) : BigDataProvider(data), Interface(7) {}
};
同样的模式也可以用于您的成员
value
。然后,接口
将是一个“纯接口”,您可以避免菱形类布局。您可以声明一个默认构造函数,而无需实现:()
该方法对于派生类应该是可见的,但不需要实现,因为只调用了另一个构造函数。Moin
首先,我认为您必须为impne
和ImpTwo
声明一个构造函数。否则,他们将在构造时尝试调用Interface()
,而这是不存在的。
其次,您可以通过使用复合模式
来避免菱形问题
class Interface // abstract
{
protected:
Base() {}
public:
virtual void f1(int &value) {}
virtual void f2(int &value) {}
}
class ImpOne: Base
{
public:
void f1(int &value) { value++; }
}
class ImpTwo : Base
{
public:
void f2(int &value) { value--; }
}
class DeviceBase // abstract base for all "Devices"
{
protected:
int value;
List<Interface*> Leaves; // use std::vector or whatever dependent
// on your library
Composite(int val) { value = val; }
public:
void f1()
{
for (Interface* const leaf : Leaves)
leaf->f1(value);
}
void f2()
{
for (Interface* const leaf : Leaves)
leaf->f2(value);
}
}
class Device : DeviceBase
{
public:
Device(int val) : DeviceBase(val)
{
Leaves << new ImpOne(value);
Leaves << new ImpTwo(value);
}
}
类接口//抽象
{
受保护的:
Base(){}
公众:
虚空f1(int&value){}
虚空f2(int&value){}
}
课程名称:Base
{
公众:
void f1(int&value){value++;}
}
第二类:基本类
{
公众:
void f2(int&value){value--;}
}
类DeviceBase//所有“设备”的抽象基
{
受保护的:
int值;
列出叶;//使用std::vector或任何依赖项
//在你的图书馆
复合(int-val){value=val;}
公众:
void f1()
{
用于(接口*常量叶:叶)
叶->f1(值);
}
无效f2()
{
用于(接口*常量叶:叶)
叶->f2(值);
}
}
类设备:DeviceBase
{
公众:
设备(int val):DeviceBase(val)
{
“整个系统崩溃”是什么意思?接口的概念(它不是C++概念)需要抽象类不包含(!)数据,但仅限于虚拟函数。如果
接口
类应该提供接口,为什么它包含一个属性值
,这些属性不适合实现类?您可以选择在默认构造函数中使引用单元化。这的确是一个奇怪的设计,但会使编译器ut up。如果构造函数未初始化引用,则会导致错误。是的,这确实很有效。我以前尝试过public and=delete,但不知何故我似乎忘记了protected。非常感谢。实际上它不起作用。出于某种原因,它似乎已编译(?困惑?),但编译器要求实现您提供的代码。@user2828383:哪个编译器?请注意,如果您从设备
派生,则每个具体的子类都应调用接口(值、数据)
(因为它使用虚拟继承)@user2828383:刚刚在MSVC 2013上测试过,我刚刚得到了警告C4250:“设备”:通过支配继承了'ImpOne::ImpOne::function1'。
。没有错误。好吧,如果我完全复制你写的内容(从url),我会得到一个链接错误:错误LNK2019:未解析的外部符号“受保护:u thiscall Interface::Interface(void)”(??0Interface)@@IAE@XZ)在函数“public:u thiscall ImpOne::ImpOne(void)”中引用(??0 ImpOne@@QAE@XZ)这很好。我最初的解决方案与之类似,但我拒绝了它,因为它包含大量的getter定义和用法。我的意思是,如果这些函数中的一个在循环中调用其他函数,并且每个调用都需要加载所有的(比如说20个)在执行一些可能无关紧要的事情之前,从远处引用元素/引用,这是对计算时间(和代码行)的极大浪费。如果函数可以直接到达元素,那么使用起来就更容易、更快。正如我在示例中所演示的,它是可以做到的(至少对于某些类型的元素)。我知道我尝试做的并不完全是纯粹的,但我这样做是因为效率高,节省了大约100行代码。首先,它相当复杂,其次,只要所有返回类型都是空的,它就可以工作。我承认这是我给出的示例,但它不适用于我的实际程序,对不起。
class Interface // abstract
{
protected:
Base() {}
public:
virtual void f1(int &value) {}
virtual void f2(int &value) {}
}
class ImpOne: Base
{
public:
void f1(int &value) { value++; }
}
class ImpTwo : Base
{
public:
void f2(int &value) { value--; }
}
class DeviceBase // abstract base for all "Devices"
{
protected:
int value;
List<Interface*> Leaves; // use std::vector or whatever dependent
// on your library
Composite(int val) { value = val; }
public:
void f1()
{
for (Interface* const leaf : Leaves)
leaf->f1(value);
}
void f2()
{
for (Interface* const leaf : Leaves)
leaf->f2(value);
}
}
class Device : DeviceBase
{
public:
Device(int val) : DeviceBase(val)
{
Leaves << new ImpOne(value);
Leaves << new ImpTwo(value);
}
}