0

我的问题是基于典型的钻石层次结构,但不是典型的钻石问题。

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

有一个抽象接口定义了许多功能(上面的例子被简化了)。然后有一些实现类一次只实现其中的几个功能。最后,还有一个非抽象类,如上面的 Device 类,通过将几个实现类组合在一起来实现整个接口。

现在,问题是这样的:

Interface 类中有一个整数元素,它由类 Device 初始化并在实现类之间共享,到目前为止一切都很好。但是如果我= 0Interface(int _value = 0)构造函数中删除,整个系统就会崩溃,因为我缺少接口类的默认构造函数,这有点奇怪,因为它永远不会被调用。

为什么这会困扰我?正如代码中所建议的,Interface 类需要包含对复杂数据结构(不属于该类)的引用,而不是在所有派生实现类之间共享。然而,为引用指定默认值既不明智也不可能。

所以问题是:

如何正确初始化接口类(引用)元素,例如SomeBigData &data代码中建议的,我无法为默认构造函数指定默认值(无论如何都不会调用)?还是我做错了什么?

4

3 回答 3

0

您可以声明一个默认构造函数而不实现:(https://ideone.com/ZD336z

class Interface
{
public:
    Interface(int _value, SomeBigData &data) : value(_value), data(data) {}
    ~Interface() {}

    virtual void function1() = 0;
    virtual void function2() = 0;
protected:
    Interface(); // No implementation
protected:
    int value;
    SomeBigData &data;
};

该方法应该对派生类可见,但不需要实现,因为只调用了其他构造函数。

于 2014-04-06T14:36:43.270 回答
0

你可以这样做:

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。然后Interface将是一个“纯界面”,您可以避免整体上的菱形类布局。

于 2014-04-06T14:04:03.330 回答
0

Moin,

Firstly, I think you have to declare a constructor for ImpOne and ImpTwo as well. Otherwise they'll try to call Interface() when contructed, which doesn't not exist. Secondly, you could avoid the diamond problem by using Composite Pattern.

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

Greez Albjeno

于 2014-04-06T15:47:01.053 回答