什么时候 child class 太不同而无法继承?
When is a child class too different to be inherited?
我有一组紧密联系的数据结构,感觉它们应该被继承。但是,它们的不同之处在于 children 有一些额外的变量。我可以通过以下方式实现:
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_} {};
}
但是如果我想遍历这些向量并访问派生的变量 class 它开始变得有点混乱:
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;
}
}
这种情况正常吗,还是我遗漏了什么,违反了一些重要的规则?我找到的大多数继承示例都没有不同的重要成员变量或方法,只是相同的实现不同。
您已经完成了创建虚拟基地的工作class。您可以重载要执行单独操作的函数,而不是将类型作为值返回。
struct A {
virtual ~A() = default;
int a;
int b;
virtual int get_value() const = 0;
A(int a_, int b_) : a{a_}, b{b_} {};
}
struct B: A {
int c;
int get_value() const override {return c;};
B(int a_, int b_, int c_) : A(a_, b_), c{c_} {};
}
struct C : A {
int d;
int get_value() const override {return d;};
C(int a_, int b_, int d_) : A(a_, b_), d{d_} {};
}
请注意,我在这里使用了 override
说明符。这是现代 c++ 中可读性和代码安全性的良好做法。
现在,我们可以使用虚函数来简化主代码
std::vector<A*> v;
v.push_back(new B(1,1,1));
v.push_back(new C(1,1,2));
for (auto* bar : v) {
std::cout << bar->get_value() << std::endl;
}
// ... do something else with v
// clean up the memory
for (auto *bar : v) {
delete bar;
}
记得在基类中定义一个虚析构函数class。这确保当我们删除向量 v
中的 A*
时,继承的 class 的析构函数也会被调用,并且我们不会发生内存泄漏。
我有一组紧密联系的数据结构,感觉它们应该被继承。但是,它们的不同之处在于 children 有一些额外的变量。我可以通过以下方式实现:
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_} {};
}
但是如果我想遍历这些向量并访问派生的变量 class 它开始变得有点混乱:
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;
}
}
这种情况正常吗,还是我遗漏了什么,违反了一些重要的规则?我找到的大多数继承示例都没有不同的重要成员变量或方法,只是相同的实现不同。
您已经完成了创建虚拟基地的工作class。您可以重载要执行单独操作的函数,而不是将类型作为值返回。
struct A {
virtual ~A() = default;
int a;
int b;
virtual int get_value() const = 0;
A(int a_, int b_) : a{a_}, b{b_} {};
}
struct B: A {
int c;
int get_value() const override {return c;};
B(int a_, int b_, int c_) : A(a_, b_), c{c_} {};
}
struct C : A {
int d;
int get_value() const override {return d;};
C(int a_, int b_, int d_) : A(a_, b_), d{d_} {};
}
请注意,我在这里使用了 override
说明符。这是现代 c++ 中可读性和代码安全性的良好做法。
现在,我们可以使用虚函数来简化主代码
std::vector<A*> v;
v.push_back(new B(1,1,1));
v.push_back(new C(1,1,2));
for (auto* bar : v) {
std::cout << bar->get_value() << std::endl;
}
// ... do something else with v
// clean up the memory
for (auto *bar : v) {
delete bar;
}
记得在基类中定义一个虚析构函数class。这确保当我们删除向量 v
中的 A*
时,继承的 class 的析构函数也会被调用,并且我们不会发生内存泄漏。