1、代码
看以下代码能编译通过吗
#include <iostream>
using namespace std;
class base
{
public:
private:
virtual void show() { cout << "base:: show"<<endl; }
int ma;
};
class derive: public base
{
public:
void show() { cout << "derive:: show "<< endl;}
private:
int mb;
};
int main()
{
base* p = new derive;
p->show();
delete p;
}
以下是这段代码编译不通过的原因分析:
访问权限问题
在C++中,对于虚函数的重写(覆盖)有访问权限相关的要求。在你给出的代码中,base
类里的虚函数show
被定义为private
,这意味着它只能在base
类的内部被访问。
虽然derive
类从语法形式上“重写”了这个虚函数,但由于base
类中show
函数的私有属性,这种重写不符合多态性中虚函数重写的正确规范。多态性要求基类中的虚函数在合适的访问权限下(通常是public
或者protected
),使得派生类能以一种符合面向对象原则的方式去重写它,进而实现通过基类指针或引用调用时能根据对象实际类型动态决定调用哪个类中重写后的函数。
在编译阶段编译器能看到的p是基类,基类里show 是私有的,不允许外部访问,那就报错了
例如,下面这样修改访问权限后,重写就能符合多态要求了:
class base
{
public:
virtual void show() { cout << "base:: show" << endl; }
private:
int ma;
};
class derive : public base
{
public:
void show() override { cout << "derive:: show " << endl; }
private:
int mb;
};
3、代码2
#include <iostream>
using namespace std;
class base
{
public:
virtual void show() { cout << "base:: show"<<endl; }
int ma;
};
class derive: public base
{
public:
private:
void show() { cout << "derive:: show "<< endl;}
private:
int mb;
};
int main()
{
base* p = new derive;
p->show();
delete p;
}
以上代码,虽然子类里的show是私有的,但是在编译阶段只看到p是基类,基类里的show 是公有的,那自然语法没有任何错误,编译正常,在运行是,p->show 是根据vfptr进行查找,找到子类的show , 然后把子类show地址放在寄存器里,直接call 寄存器,;
运行时多态和非多态在汇编来看,最明显的差异就是,非多态直接call函数地址,多态call 寄存器里存放的地址。