Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;如何初始化抽象基类引用元素?_C++_Inheritance_Virtual Inheritance_Diamond Problem - Fatal编程技术网

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