我正在实现一个简单的层次结构: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
完整,从而可以实例化 Derived
objects),代码将编译干净。
这里有两个可能的教训:
- 完成您开始的工作。如果我没有将
SubType
的模拟完成一半,就不会出现这种情况。 - 如果 linter 令人困惑,请查看构建的完整错误输出。
1 特别是我声明了一个成员,其中我还没有覆盖继承的抽象虚方法。
关于c++ - 无法使用类型为 'Parent' 的表达式初始化类型为 'Derived' 的对象参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55856187/