#include <iostream>
using namespace std;
class Person
{
public:
void P(){ cout << "Person P" << endl; }
virtual void Print(){ cout << "Person Print" << endl; }
Person(){ cout << "Constructor Person" << endl; }
virtual ~Person(){ cout << "Dectructor Person" << endl; }
};
class Developer : public Person
{
public:
void Pi() { cout << "Developer Pi" << endl; }
void Print() override
{
cout << "Developer Print" << endl;
}
Developer(){ cout << "Constructor Develoeper" << endl; }
~Developer(){ cout << "Dectructor Develoer" << endl; }
};
int main()
{
Person *p = new Person();
Developer* d = dynamic_cast<Developer*>(p);
d->Pi();
delete p;
delete d;
return 0;
}
输出:
Constructor Person
Developer Pi
Dectructor Person
为什么我可以调用Developer
的函数Pi
?
如何在没有Pi
的构造函数的情况下调用Developer
?
请注意,Pi
仅在课程Developer
中声明。
答案 0 :(得分:3)
你做不到。您的代码具有未定义的行为。如果我将main()
函数修改为:
int main()
{
Person *p = new Person();
Developer* d = dynamic_cast<Developer*>(p);
assert(d!=0);
d->Pi();
delete p;
delete d;
return 0;
}
然后触发断言d!=0
。这表明dynamic_cast
失败了。你在空指针上调用Developer::Pi
,并且使用你的编译器它运行正常,可能是因为Developer::Pi
没有使用this
。
答案 1 :(得分:2)
Developer* d = dynamic_cast<Developer*>(p);
你有d == nullptr
。
d->Pi();
您调用未定义的行为:
方法通常等效到一个函数,该函数需要额外的this
作为参数,因为你不使用this
这个方法似乎适用于你的情况。
答案 2 :(得分:0)
这是因为dynamic_cast。您没有引用实例中的任何变量,因此它不会失败。
访问任何虚拟方法或访问将存储在对象中的任何内容都会导致访问冲突。
答案 3 :(得分:0)
通过声明d是指向Developer类对象的指针,您可以向编译器提示。您还声明void Pi()不是虚拟的,因此编译器使用早期绑定(编译时)。这意味着在编译期间调用的函数的地址是固定的,并且不需要评估对象(与虚方法不同)
当调用d-&gt; Pi()时,它与你用Pi取得指向Developer实例的指针调用Pi(d)相同。在MFC中有一个名为Validate的方法或类似的方法,它使用相同的机制来检查你的指针是否为空:)
你没有在删除d上崩溃,因为它在标准中,删除空指针是正常的,什么都不做(删除脏指针是未定义的强硬)。
只需将单词virtual添加到Pi方法签名中或向Developer类添加一个字段,并尝试在Pi方法中修改该字段。然后你会看到差异;)