c++ - 无法使用类型为 'Parent' 的表达式初始化类型为 'Derived' 的对象参数

标签 c++ inheritance

我正在实现一个简单的层次结构:System 和 Device 将是两个基类。系统有设备。然后我会有一个从系统派生的网络,它将有计算机。计算机派生自系统和设备。最后,计算机有各种设备,如 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;
};

计算机的 addComponent() 有一个错误,因为不能用 Computer 类型的表达式初始化 System 类型的对象参数。我不完全确定这意味着什么,因为该函数是从 Computer 类调用的,它是一个设备,因此它应该可以访问父级的 addDevice()。该函数的参数是一个设备。

同样令人困惑的是我的 Network 类,其中函数 addComputer() 使用同一组指令没有错误。

谁能解释一下我的设计有何缺陷?

最佳答案

今天,当我正在编写派生类的代码时,这条错误消息突然出现,在我的例子中,关键是派生类——就在那一刻——未实例化。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 完整,从而可以实例化 Derivedobjects),代码将编译干净。

这里有两个可能的教训:

  • 完成您开始的工作。如果我没有将 SubType 的模拟完成一半,就不会出现这种情况。
  • 如果 linter 令人困惑,请查看构建的完整错误输出。

1 特别是我声明了一个成员,其中我还没有覆盖继承的抽象虚方法。

关于c++ - 无法使用类型为 'Parent' 的表达式初始化类型为 'Derived' 的对象参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55856187/

相关文章:

C++:在继承链中放置构造函数的位置?

Javascript继承构造函数

javascript - for-in 与没有继承属性的 Object.keys forEach

c++ - 为什么我不能使用 getter 访问公共(public)变量?

c++ - reference_wrapper 和 std::ref 是如何工作的?

c++ - 无法在赋值中将 'clist<int>::node*' 转换为 'clist<char>::node*'

c++ - 为什么将 std::string 传递给 CString.Format() 有时只会崩溃?

c++ - C++中的字符串连接问题

c++ - error LNK2001继承问题

codeigniter - 如何在 CodeIgniter 中从另一个模型继承一个模型