有人可以解释为什么Driver
init()
方法无法打印在子级中覆盖的name
属性吗?
#include <iostream>
#include <string>
class Driver {
public:
std::string name = "Unknown";
void init() {
std::cout << name << std::endl;
}
};
// need public here to inherit init()
class SpecificDriver : public Driver {
public:
std::string name = "Specific";
};
int main() {
Driver d;
SpecificDriver sd;
// this gives Unknown Unknown =/
d.init();
sd.init();
}
这给出了:
Unknown
Unknown
应该是:
Unknown
Specific
答案 0 :(得分:4)
你的表现并不像你认为的那样。您在驱动程序中声明变量“name”,在SpecificDriver中声明变量“name”。当您调用基类驱动程序中定义的init()
时,该驱动程序只能访问其值为“unknown”的name
字段。
相反,您应该使用构造函数初始化“name”变量。
像这样:
class Driver {
public:
std::string name;
Driver():name("Unknown"){} //default
Driver(std::string value):name(value){}
void init() {
std::cout << name << std::endl;
}
};
// need public here to inherit init()
class SpecificDriver : public Driver {
public:
SpecificDriver():Driver("Specific"){}
};
int main() {
Driver d;
SpecificDriver sd;
d.init();
sd.init();
}
答案 1 :(得分:2)
在C ++中,虚拟继承是选择加入而不是隐式的。
当你有这个代码时
class Driver {
public:
std::string name = "Unknown";
void init() {
std::cout << name << std::endl;
}
};
符号name
将根据当时的范围静态解析。
如果稍后声明全局变量name
,则它对此代码的含义没有影响。如果您稍后从此类Driver
派生,init
函数在继承该类时,则不会有不同的含义,如您的示例所示。
这&#34;静态&#34; dispatch是C ++中的默认行为,因为它是最简单和最快的行为。特别是,如果你以后使用模板和继承来做这件事很重要,否则很多代码会有很多额外的开销。
Alex Zywicki展示了一种可以达到你想要的方式。另一种方法是使用虚拟分派来获取字符串。像这样:
class Driver {
public:
virtual std::string name() const {
return "Unknown";
}
void init() {
std::cout << name() << std::endl;
}
};
class SpecificDriver : public Driver {
virtual std::string name() const override {
return "Specific";
}
};
答案 2 :(得分:0)
可以通过CRTP访问子类的类成员。
#include <iostream>
template <typename Derived>
class Driver {
public:
void init() {
std::cout << static_cast<Derived*>(this)->name << std::endl;
std::cout << Derived::value << std::endl;
}
};
class SpecificDriver : public Driver<SpecificDriver> {
public:
std::string name = "Specific";
static constexpr char* value = "Another specific string";
};
int main() {
SpecificDriver g;
g.init();
}
如果您需要一个公共基类来存储这些内容,或者与正常的多态行为相结合,您可以使模板类Driver
继承自公共基类。