一、虚函数
- 在类的定义中,前面有
virtual
关键字的成员函数称为虚函数; virtual
关键字只用在类定义里的函数声明中,写函数体时不用。-
class Base { virtual int Fun() ; // 虚函数 }; int Base::Fun() // virtual 字段不用在函数体时定义 { }
二、多态的表现形式
派生类的指针(对象) 可以赋给 基类指针(引用);
通过基类指针(引用)调用基类和派生类中的同名虚函数时:
1.若该指针(引用)指向一个基类的对象,那么被调用的是基类的虚函数;
2.若该指针(引用)指向一个派生类的对象,那么被调用的是派生类的虚函数。
这种机制就叫做多态,即调用哪个虚函数,取决于指针(引用)指向哪种类型的对象
// 基类
class CFather
{
public:
virtual void Fun() { } // 虚函数
};
// 派生类
class CSon : public CFather
{
public :
virtual void Fun() { }
};
int main()
{
CSon son;
CFather *p = &son;
p->Fun(); //调用哪个虚函数取决于 p 指向哪种类型的对象
//引用形式:
//CFather &r = son;
//r.Fun();
return 0;
}
作者:小林coding
链接:https://zhuanlan.zhihu.com/p/104605966
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
上例子中的 p(r)
指针(引用)指向的是 CSon
类对象,所以 p->Fun()
(r.Fun()
)调用的是 CSon
类里的 Fun
成员函数。
三、多态作用
在面向对象的程序设计中使用“多态”,能够增强程序的可扩展性,即程序需要修改或增加功能时,需要改动和增加的代码较少。
四、多态在函数中的体现
1.在非构造函数、非析构函数的成员函数中调用 虚函数 ,是多态
下面的代码,pBase->fun1()
输出结果是什么呢?
class Base
{
public:
void fun1()
{
fun2();
}
virtual void fun2() // 虚函数
{
cout << "Base::fun2()" << endl;
}
};
class Derived : public Base
{
public:
virtual void fun2() // 虚函数
{
cout << "Derived:fun2()" << endl;
}
};
int main()
{
Derived d;
Base * pBase = & d;
pBase->fun1();
return 0;
}
pBase
指针对象虽然指向的是派生类对象,但是派生类里没有 fun1
成员函数,则就调用基类的 fun1
成员函数,Base::fun1()
里又会调用基类的 fun2
成员函数,所以输出结果是Base::fun2()
这时修改下代码
class Base
{
public:
void fun1()
{
this->fun2(); // this是基类指针,fun2是虚函数,所以是多态
}
}
this 指针的作用就是指向成员函数所作用的对象,所以非静态成员函数中可以直接使用this来代表指向该函数作用的对象的指针。
pBase指针对象指向的是派生类对象,派生类中没有fun1成员函数,所以就会调用基类的fun1的成员函数,在Base::fun1()成员函数体里执行this->fun2()时,实际上指向的是派生类对象fun2成员函数。
所以正确的输出结果是:Derived:fun2()
2.在构造函数和析构函数中调用 虚函数,不是多态。编译时即可确定,调用的函数是自己的类或基类中定义的函数,不会等到运行时才决定调用自己的还是派生类的函数。
例子
// 基类
class CFather
{
public:
virtual void hello() // 虚函数
{
cout<<"hello from father"<<endl;
}
virtual void bye() // 虚函数
{
cout<<"bye from father"<<endl;
}
};
// 派生类
class CSon : public CFather
{
public:
CSon() // 构造函数
{
hello();
}
~CSon() // 析构函数
{
bye();
}
virtual void hello() // 虚函数
{
cout<<"hello from son"<<endl;
}
};
int main()
{
CSon son;
CFather *pfather;
pfather = & son;
pfather->hello(); //多态
return 0;
}
输出结果
hello from son // 构造son对象时执行的构造函数
hello from son // 多态
bye from father // son对象析构时,由于CSon类没有bye成员函数,所以调用了基类的bye成员函数