iag*_*ito 12 c++ polymorphism interface multiple-inheritance
谁能帮我理解这种行为?简而言之:
以下是我将其归结为:
#include <iostream>
#include <vector>
// A base class
struct Base {
// A polymorphic method
virtual void describe() const {
std::cout << "Base" << std::endl;
};
virtual ~Base(){
std::cout << " Base destroyed" << std::endl;
};
};
// A specific interface
struct Interface {
virtual ~Interface(){
std::cout << " Interface Destroyed" << std::endl;
};
virtual void specific() = 0;
};
// A derived class..
struct Derived : public Base, public Interface {
virtual void describe() const {
std::cout << "Derived" << std::endl;
};
virtual void specific() {
std::cout << "Derived uses Interface" << std::endl;
};
virtual ~Derived() {
std::cout << " Derived destroyed" << std::endl;
};
};
int main() {
// Test polymorphism:
Base* b( new Base() );
Derived* d( new Derived() );
b->describe(); // "Base"
d->describe(); // "Derived"
// Ok.
// Test interface:
d->specific(); // "Derived uses Interface"
Interface* i(d);
i->specific(); // "Derived uses Interface"
// Ok.
// Here is the situation: I have a container filled with polymorphic `Base`s
std::vector<Base*> v {b, d};
// I know that this one implements the `Interface`
Interface* j((Interface*) v[1]);
j->specific(); // " Derived destroyed"
// " Interface destroyed"
// " Base destroyed"
// Why?! What did that object do to deserve this?
return EXIT_SUCCESS; // almost -_-
}
Run Code Online (Sandbox Code Playgroud)
谁能告诉我我在那里失踪了什么?
有趣的事实:如果我交换了Base::~Base和的定义Base::describe,那么对象描述自己而不是被销毁.为什么命令在方法声明中很重要?
Bar*_*rry 21
这是避免C风格演员阵容的一个很好的理由.当你这样做时:
Interface* j((Interface*) v[1]);
Run Code Online (Sandbox Code Playgroud)
那是一个reinterpret_cast.A C风格的类型转换会尽量做到,依次是:const_cast,static_cast,static_cast然后const_cast,reinterpret_cast,reinterpret_cast然后const_cast.在这种情况下,所有这些演员都是错的!reinterpret_cast特别是只是未定义的行为,老实说甚至不重要为什么你看到你看到的具体行为†.未定义的行为未定义.
你想要做的是:
Interface* j = dynamic_cast<Interface*>(v[1]);
Run Code Online (Sandbox Code Playgroud)
这是通过运行时动态层次结构的正确转换 ,并将为您提供正确的Interface*对应v[1](或者nullptr,如果v[1]没有此运行时类型).一旦我们修复了它,然后j->specific()打印Derived uses Interface,就像你期望的那样.
Base没有a specific,因此该特定函数的偏移量可能与之对齐~Base(),因此效果是您直接调用析构函数 - 这就是您看到所看到的内容的原因.
| 归档时间: |
|
| 查看次数: |
627 次 |
| 最近记录: |