无法使用“派生”类型的表达式初始化“父母”类型的对象参数

时间:2019-04-25 19:14:03

标签: c++ inheritance

我正在实现一个简单的层次结构:系统和设备将是两个基类。系统具有设备。然后,我将有一个从系统派生的网络,它将有计算机。计算机来自系统和设备。最后,计算机具有各种设备,如CPU,内存等。之所以将计算机作为设备,是因为网络是系统,而系统存储设备。计算机是系统的原因是因为它存储设备(CPU,内存等)

无论如何,到目前为止,我的实现是

class Device {
public:
    explicit Device(unsigned property): property(property) {}
    friend void swap(Device &first, Device &second) {
        using std::swap;
        swap(first.property, second.property);
    }
    Device& operator=(Device other) {
        swap(*this, other);
        return *this;
    }
private:
    Device() = default;

    unsigned property;
};

class System {
public:
    explicit System(const string &name): name(name) {}
    friend void swap(System &first, System &second) {
        using std::swap;
        swap(first.name, second.name);
        swap(first.devices, second.devices);
    }
    System& operator=(System other) {
        swap(*this, other);
        return *this;
    }
protected:
    void addDevice(Device b1) {
        devices.push_back(b1);
    }
private:
    vector<Device> devices;
    string name;
};

class Computer: public System, public Device {
public:
    Computer(unsigned property, const string& name): System(name), Device(property) {}

    Computer& addAddress(const string &address) {
        addresses.emplace_back(address);
        return *this;
    }
    Computer& addComponent(Device newDevice) {
        System::addDevice(newDevice); //error
        return *this;
    }
private:
    vector<const string> addresses;
};

class Network: public System {
public:
    Network(const string& name): System(name) {}

    Network& addComputer(Device newComputer) {
        System::addDevice(newComputer); //no error
        return *this;
    }
};

class CPU: public Device {
public:
    CPU(unsigned coreCount, unsigned frequency): Device(coreCount), frequency(frequency) {}
private:
    unsigned frequency;
};

由于cannot initialize object parameter of type System with an expression of type Computer,计算机的addComponent()出错。我不完全确定这是什么意思,因为该函数是从Computer类(它是Device)调用的,因此它应该可以访问父级的addDevice()。函数具有的参数是设备。

我的Network类(其中函数addComputer()使用相同的指令集)没有错误也令人困惑。

有人可以解释我的设计有何缺陷吗?

2 个答案:

答案 0 :(得分:0)

您不能拥有std::vector基类实例并将派生实例保存到其中。使用指向向量中基类的指针,例如std::vector<std::shared_ptr<Device>>

答案 1 :(得分:0)

今天,当我正在对派生类进行编码的过程中,此错误消息为我弹出。在我的情况下,关键是派生类-就在那一刻-不可思议。 > 1

一旦我在派生类上取得足够的进展以实例化它,错误就会消失。

原因

您正在键入的派生调用当前无法实例化。

演示

请考虑以下具有两个继承关系的代码。

class Type {
public:
    Type(){}
    virtual ~Type() {}
    virtual void m() = 0;
};

class SubType: public Type {
public:
    SubType(): Type() {}
    virtual ~SubType() {}
    // virtual void m() override; // <== Important code commented out here
};
// void SubType::m() {}           // <== and here


class Base {
public:
    Base() {};
    virtual ~Base() {}
    virtual void m();
};

class Derived: public Base, public Type {
public:
    Derived(): Base() {}
    virtual ~Derived() override {}
    virtual void m() override;
protected:
    SubType m_troublesome;  // <== Note member here has incomplete type when
                            //     comments are in place
};

void Base::m() {}

void Derived::m() {
    Base::m();              // <== Tricky error message on this line
}

尝试使用

进行编译
$ clang --std=c++11 -Wall -pedantic -c test.cc

您会收到反馈

test.cc:34:13: error: field type 'SubType' is an abstract class
    SubType m_troublesome;
            ^
test.cc:8:18: note: unimplemented pure virtual method 'm' in 'SubType'
    virtual void m() = 0;
                 ^
test.cc:42:11: error: cannot initialize object parameter of type 'Base' with an
      expression of type 'Derived'
    Base::m();

如果同时看到这三个,则知道从哪里开始,但是如果您将clang用作linter(就像许多IDE一样),那么您可能会看到第三个(在Base::m();行中,隔离的完全有效的代码段)中的内容与前两个内容不同。

即时混乱

如果从代码的两个标记部分中删除注释(使SubType完成并因此可以实例化Derived对象),则代码将干净地编译。

此处有两个可能的教训:

  • 完成您的开始。如果我还没有完成SubType的类比,那情况将永远不会发生。
  • 如果linter令人困惑,请查看构建的完整错误输出。

1 特别是我声明了一个成员,而该成员的类型尚未覆盖继承的抽象虚拟方法。