【发布时间】:2021-06-24 16:06:24
【问题描述】:
我有一组紧密相连的数据结构,感觉它们应该被继承。但是,它们的不同之处在于孩子有一些额外的变量。我可以通过以下方式实现:
struct A {
int a;
int b;
virtual int kind()=0;
A(int a_, int b_) : a{a_}, b{b_} {};
}
struct B: A {
int c;
int kind() {return 1;};
B(int a_, int b_, int c_) : A(a_, b_), c{c_} {};
}
struct C : A {
int d;
int kind() {return 2;};
C(int a_, int b_, int d_) : A(a_, b_), d{d_} {};
}
但是如果我想遍历这些向量并访问派生类的变量,它开始变得有点混乱:
std::vector<A*> v;
v.push_back(new B(1,1,1));
v.push_back(new C(1,1,2));
for (A* bar : v) {
if (bar->kind() == 1) {
auto *bar_ = dynamic_cast<B*>(A);
std::cout << bar_->c << std::endl;
} else if (bar->kind() == 2) {
auto *bar_ = dynamic_cast<C*>(A);
std::cout << bar_->d << std::endl;
}
}
这种事情是正常的,还是我错过了什么并违反了一些重要的规则?我发现的大多数继承示例没有不同的重要成员变量或方法,只是相同的实现方式不同。
【问题讨论】:
-
作为一个好的经验法则,任何
dynamic_cast的使用都是一个危险信号:你的设计有问题。 -
我会说这是一个糟糕的设计选择。如果您有指向基类的指针并希望通过它访问对象,您应该有一个统一的接口。所以可以处理所有对象,而不必关心它们是什么类型。否则,也许您应该以不同的方式开始存储它们。
-
在不相关的注释中,您应该使用
std::vector<std::unique_ptr<A>>,这样您就不必处理手动内存管理。 -
dynamic_cast<B *>(A);很奇怪,你应该转换一个变量,而不是一个类型,你的意思可能是auto *bar_ = dynamic_cast<B *>(bar); -
根据经验,使用
dynamic_cast向下转换(例如将Base *转换为Derived *)是一个非常重要的提示,即派生类不应从基类派生.在您的情况下,一个更简单的设计是基类提供一个名为(例如)toString()的virtual函数,以将对象的所有数据打印到字符串和(如果需要)toDerivedString()执行相同的操作,但仅适用于最派生的类成员(默认情况下不打印任何内容)。然后,您的循环可以直接调用这些函数 - 无需测试对象的实际类型。
标签: c++ pointers inheritance vector polymorphism