【发布时间】:2021-04-13 14:32:20
【问题描述】:
其实here和there也问过类似的问题,但答案都不满意。代码示例是
class CBase
{
public:
virtual void act1(){cout<<"CBase::act1()! "<<endl; act2();}
void act2() {cout<<"CBase::act2()! "<<endl; act3();}
virtual void act3(){cout<<"CBase::act3()! "<<endl; act4();}
virtual void act4(){cout<<"CBase::act4()! "<<endl; act5();}
void act5() {cout<<"CBase::act5()! "<<endl; }
virtual ~CBase(){}
} ;
class CDerive : public CBase
{
public:
void act3(){cout<<"CDerive::act3()! "<<endl; act4();}
void act4(){cout<<"CDerive::act4()! "<<endl; act5();}
void act5(){cout<<"CDerive::act5()! "<<endl; }
virtual ~CDerive(){}
} ;
int main()
{
CBase *p=new CDerive;
p->act1();
cout<<endl;
p->act5();
delete p;
return 0;
}
输出是
CBase::act1()!
CBase::act2()!
CDerive::act3()!
CDerive::act4()!
CDerive::act5()!
CBase::act5()!
关于p->act1()
- 由于
act1()是一个虚函数,派生类没有实现它,所以程序会调用CBase::act1(); - 然后程序会调用
CBase::act2(); -
act3()是虚拟函数,程序会调用CDervie::act3(); -
act4()也是虚拟函数,程序会调用CDervie::act4(); - 来了我不明白的部分,
act5()不是虚函数,而p是属于CBase的指针,基本上p只能访问CBase中的函数!但输出是CDerive::act5()!
相比之下,p->act5() 会像我想的那样调用CBase::act5()。
原理——基类指针只能访问基类和虚函数中定义的函数,与真正的输出之间似乎存在矛盾。原因也无法从虚拟表中解释,因为CDerive::act5() 甚至不在虚拟表中。所以,我的问题是
- 这些背后的基本原理是什么?
-
CBase *p=new CDerive或CDerive a; CBase *p=&a时发生了什么?
【问题讨论】:
-
你从
CDerive::act4调用act5...静态类型就是CDerive。 -
可能相关(甚至重复?):stackoverflow.com/q/67065428/10871073
-
在第一种情况下,访问
act5的不是p,而是CDerive实例本身,在CDerive::act4内部。当你从另一个成员函数中调用一个非虚拟成员函数时,它是根据该成员函数中*this的静态类型来选择的。 -
@AdrianMole 真巧,我们俩同时问了同样的问题
-
@molbdnilo 我想我明白你的意思。非常感谢,我会在下面写下我的理解。
标签: c++ polymorphism