我正在尝试在其继承树中的一个类的构造函数中发现对象的派生类最多的类。我现在已经花了几个小时在这上面,我不知道我怎么做,或者为什么它没有意义。它似乎很有道理,但却拒绝工作。我找到了很多关于RTTI的页面,并且基本上没有它们。我会在我的测试用例及其输出后继续解释。
来源:
#include <iostream>
#include <typeinfo>
#include <string>
class A
{
public:
A(std::string foo);
virtual void bar(A* a) = 0;
};
class B : public A
{
public:
B();
virtual void bar(A* a);
};
A::A(std::string foo)
{
std::cout << "type as passed to A constructor: " << foo << " (" << this << ")" << std::endl;
std::cout << "type as determined in A constructor: " << typeid(*this).name() << " (" << this << ")" << std::endl;
}
B::B() : A(typeid(*this).name())
{
A* a = (A*)this;
std::cout << "type as determined in B constructor: " << typeid(*a).name() << " (" << this << ")" << std::endl;
this->bar(this);
}
void B::bar(A* a)
{
std::cout << "type as determined in bar: " << typeid(*a).name() << " (" << a << ")" << std::endl;
}
int main()
{
B b;
b.bar(&b);
return 0;
}
输出(在g ++上):
type as passed to A constructor: 1B (0x7fff5fbff910)
type as determined in A constructor: 1A (0x7fff5fbff910)
type as determined in B constructor: 1B (0x7fff5fbff910)
type as determined in bar: 1B (0x7fff5fbff910)
type as determined in bar: 1B (0x7fff5fbff910)
我试图让输出的第二行说“1B”而不是“1A”。 RTTI是否因为某种原因而无法想象?这怎么不打破虚函数的想法呢?(我用虚函数实现了这个,直到我发现我重新实现了RTTI的一部分,我以前不知道。)如输出所示,我可以如果我避免使用“这个”,那就做这个工作,但是这样做的需要看起来像设计上的破坏。
答案 0 :(得分:4)
你不能这样做是因为你误解了所涉及的动态。
规则是:
任何类的构造函数/析构函数中的
this
指向其构造函数/析构函数的类。
此外,这就是构造函数中调用的virtual
函数的行为与使用动态调度时通常期望virtual
函数无效的原因。
在调用构造函数之后,您应该检测类型,。您可以在除构造函数和析构函数之外的任何成员函数中执行此操作。
答案 1 :(得分:3)
您看到了预期的行为。在构造函数体中,正在构造的对象的类型与正在执行构造函数的类的类型相同,而不是正在构造的派生类最多的类。
当在成员初始化表达式中使用时,异常实际上在表达式typeid(*this)
中。这在C ++ 03中曾经是未定义的行为但是在C ++ 11中已经改变了,所以你得到的是构造函数类的类型而不是实际对象的类型待建。
答案 2 :(得分:0)
考虑你的继承关系,你应该已经知道A
的构造函数将首先执行,然后B
的构造函数将执行。在A
的构造函数中,该对象尚未构造B
,因为它尚未构造。因此,构造函数中对象的动态类型始终是类本身的类型,而不是派生类的类型。析构函数也是如此。
简而言之,在施工时无法完成您想做的事。