父类指针、子类指针指向子类对象的问题
父类:B
派生类:D
🐳如果父类指针(pb)调用的是 non-virtual函数
Non-virtual函数都是 静态绑定的,那么通过pb(point-to-B)调用的 non-virtual函数永远是在class B中定义的版本,即使pb指向的是派生类对象
#include <iostream>
using namespace std;
class B
{
public:
void foo() {
cout << "calling B's foo\n";
}
};
class D : public B
{
public:
void foo() {
cout << "calling D's foo\n";
}
};
int main()
{
D objd;
B * pb = &objd;
pb -> foo();
return 0;
}
//calling B's foo
如果说删掉父类中foo函数呢?答案是会报错而不会调用子类的foo函数
main.cpp:22:11: error: no member named 'foo' in 'B' pb -> foo(); ~~ ^
🐣子类指针调用
子类指针一般是不会指向父类的对象的,我也就不考虑了。
子类指针指向子类的对象也就没什么好说的,相当于直接对象使用自己的函数
🐱父类、子类指针调用的是virtual 函数
D objd
: 子类对象
#include <iostream>
using namespace std;
class B
{
public:
virtual void foo() {
cout << "calling B's foo\n";
}
};
class D : public B
{
public:
virtual void foo() {
cout << "calling D's foo\n";
}
};
int main()
{
D objd;
B * pb = &objd;
pb -> foo(); //父类指针调用子类的虚函数,动态类型是D*,因为指向的对象是D类型
D * pd = &objd;
pd -> foo(); //子类指针调用子类的虚函数,静态、动态类型都是D*
return 0;
}
//calling D's foo
//calling D's foo
不论是pb还是pd指向子类的对象,调用虚函数foo都会调用
D::foo
,因为pb和pd指向的都是一个类型为D的对象
因此:不要重新定义继承而来的non-virtual函数,因为调用非虚函数的时候使用的是静态绑定(由指针的类型决定而不是对象),具体的使用子类的还是父类定义的non-virtual函数取决于
指向对象的指针的类型
,如果父类指针调用子类函数其实执行的是父类的non-virtual函数
新🌰 样例来源
#include <iostream>
using namespace std;
class A
{
public:
virtual void foo()
{
cout << "A's foo()" << endl;
bar();
}
virtual void bar()
{
cout << "A's bar()" << endl;
}
};
class B: public A
{
public:
void foo()
{
cout << "B's foo()" << endl;
A::foo();
}
void bar()
{
cout << "B's bar()" << endl;
}
};
int main()
{
B bobj;
A *aptr = &bobj;
aptr->foo();
A aobj = *aptr; //转化为A类对象
aobj.foo();
}
B's foo() //正常,动态类型是B类的,调用B的
A's foo() //正常,调用A::foo嘛
B's bar() //注意⚠️
在foo函数中,调用了bar()函数,其实真正的应该是this -> bar(),我们的对象其实是B类型的,因此调用的是B的bar
A's foo() //正常
A's bar() //正常