其实,类似的问题这里问过,那里问过,但回答都不满意。代码示例是
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
?
我将重新陈述你的要点,并对它们做一些小的修改。
act1()
是一个非抽象的、公共的虚函数,它存在于cbase
中,而不存在于cderive
中,因此p
使用了cbase
中的实现。因为它是在CBASE
中实现的,所以不需要在子类中重写act2()
相同。请注意,act2()
是非虚拟act3()是
CBASE中的虚函数,在
CDerive中被重写。由于
P被分配为
CDerive,因此使用重写,并从
CDerive`
- 与上述
act4()
相同
- 因为上面的
act4()
是从CDerive
对象调用的,所以对act5()
的调用也将来自CDerive
新建项目符号:
p->act5()
调用CBASE
版本。这是因为P
是CBASE*
,act5()
不是虚拟的。因此它从cbase