将 void* 强制转换为多个继承类的超类不会调用正确的方法
Casting a void* to super classes of multple inherited class doesn't call the right method
我将指向一组异构对象的指针列表存储在容器中,并使用字符串来标识它们。关于这次操作的安全性,我已经在这里讨论过了,我对此很好。
问题是,当类具有多重继承并且我尝试将同一指针强制转换为一个或另一个超类时,似乎第二个转换失败了。
下面是一个示例:
#include <iostream>
#include <map>
using namespace std;
class A {
public:
virtual void hello() = 0;
};
class B {
public:
virtual void goodbye() = 0;
};
class C : public A,
public B
{
public:
void hello() override {
std::cout << "C says: Hello World!" << std::endl;
}
void goodbye() override {
std::cout << "C says: GoodBye World!" << std::endl;
}
};
class D : public A {
public:
void hello() override {
std::cout << "D says: Hello World!" << std::endl;
}
};
class E : public B {
public:
void goodbye() override {
std::cout << "E says: GoodBye World!" << std::endl;
}
};
int main()
{
std::map <std::string, void*> mymap;
C c;
D d;
E e;
mymap["C"] = (void*) &c;
mymap["D"] = (void*) &d;
mymap["E"] = (void*) &e;
static_cast<A*>(mymap["D"])->hello();
static_cast<B*>(mymap["E"])->goodbye();
static_cast<A*>(mymap["C"])->hello();
static_cast<B*>(mymap["C"])->goodbye();
return 0;
}
预期输出为:
D says: Hello World!
E says: GoodBye World!
C says: Hello World!
C says: GoodBye World!
但我得到的是:
D says: Hello World!
E says: GoodBye World!
C says: Hello World!
C says: Hello World!
我什至不知道这怎么可能,因为我什至没有打电话给hello
.
编辑在了解了副本和此页面中讨论的内容后,我最终得到了这个解决方案:
int main()
{
std::map <std::string, void*> mymap;
C c;
D d;
E e;
mymap["C"] = static_cast<A*>(&c);
mymap["D"] = static_cast<A*>(&d);
mymap["E"] = static_cast<B*>(&e);
static_cast<A*>(mymap["D"])->hello();
static_cast<B*>(mymap["E"])->goodbye();
static_cast<A*>(mymap["C"])->hello();
dynamic_cast<B*>(static_cast<A*>(mymap["C"]))->goodbye();
return 0;
}
我发现的另一种解决方案是使第二个类继承前一个类:
...
class B : public A{
public:
virtual void goodbye() = 0;
};
class C : public B
{
public:
void hello() override {
std::cout << "C says: Hello World!" << std::endl;
}
void goodbye() override {
std::cout << "C says: GoodBye World!" << std::endl;
}
};
...
int main()
{
std::map <std::string, void*> mymap;
C c;
D d;
mymap["C"] = static_cast<A*>(&c);
mymap["D"] = static_cast<A*>(&d);
static_cast<A*>(mymap["D"])->hello();
static_cast<A*>(mymap["C"])->hello();
dynamic_cast<B*>(static_cast<A*>(mymap["C"]))->goodbye();
return 0;
}
您的代码具有未定义的行为。
给定一个转换为B*
void*
,计算机没有办法知道B
子对象在哪里(在指向的东西中,实际上是一个C
(。你只是假装整个事情(或者,至少,它的前缀(是一个B
,如果它是一个简单的单一继承,那将是真的...... 但你的不是;第一个碱基是A
,不是B
。
不要像这样使用void*
擦除类型。
相关文章:
- 在从给定超类继承的所有类上调用虚函数
- 按值将对象传递给 SubClass 构造函数,导致超类的构造函数不调用
- 将 void* 强制转换为多个继承类的超类不会调用正确的方法
- 我可以从我的超类调用子类构造函数吗?
- C++ 如何使用一个参数从派生类构造函数中调用具有两个参数的超类构造函数
- 如何在 c++ 中从模板基类的构造函数调用模板超类的构造函数?
- 子类/超类的"无匹配函数调用"
- 从构造函数的主体调用超类构造函数
- 调用超类函数继承 c++
- C ++如何使用子类调用函数,具有超类指针
- 在子类的构造函数中调用超类的构造器两次
- 超类和子类,不同的函数调用取决于子类
- 调用子重写时,始终调用超类虚拟函数
- C++调用同一虚拟函数的超类函数
- C++调用模板化超类的继承方法
- 从超类调用子类的方法
- 为什么超类 B 调用子类 A 的方法?
- 超类调用子类方法的STL迭代器
- 从vector的超类调用子类方法
- 从超类调用子类方法