虚函数

虚函数

运行时的多态性

• virtual

• 我们以相同的指令却唤起了不同的函数,这称为“多态性”。编译器无法在编译期间判断到底呼叫哪个函数,必须到执行期间才能评估,这称为后期绑定(late binding)或 动态绑定(dynamic binding)。

• 对于non-virtual函数,在编译期间就转换成为一个固定的地址的呼叫,这称为前期绑定(earlybinding)或静态绑定(static binding)。

注意事项

• 一旦一个函数被声明为虚函数,即使重新定义类时没有声明虚函数,那么它从该点之后的继承层次结构中都是虚函数。
• 虽然函数在类层次结构的高层中声明为虚函数会使它在低层隐式地成为虚函数,但有些程序员为了提高程序的清晰性更喜欢在每一层中显式地声明这些虚函数。
• 没有定义虚函数的派生类简单地继承其直接基类的虚函数。

纯虚函数

• 纯虚函数不需要定义其实际动作,它的存在只是为了在派生类中被重新定义。

class Shape {
public:
virtual void printShapeName() =0;
};

抽象类与具体类
• 含有纯虚函数的类我们称为抽象类。
• 不能定义抽象类变量实体,但可以定义指向抽象类的指针。
• 如果基类是抽象类,它的派生类如果没有改写基类中的纯虚函数,那么它的派生类也就成为一个抽象类了。
• 不含有纯虚函数的类我们称为具体类。

下面举一个小例子:

#include<iostream>
using namespace std;

class CChar{
public:
    int X,Y;
    CChar(int x,int y){X=x;Y=y;}
    virtual void Set_M(){int Z=X*Y;cout<<Z<<endl;}
    void Set(){Set_M();}
};

class A:public CChar{
public:
    int Z;
    A(int i,int j,int k):CChar(i,j){Z=k;}
    void Set_M(){int q=X+Y+Z;cout<<q<<endl;}
};
class B:public CChar{
public:
    int Z;
    B(int i,int j,int k):CChar(i,j){Z=k;}
    void Set_M(){int q=X+Y-Z;cout<<q<<endl;}
};

int main()
{
    CChar cchar(1,2);
    A a(1,2,3);
    B b(1,2,3);

    cchar.Set();
    a.Set();
    b.Set();
    return 0;
}

其中的Set_M()函数是虚函数,CChar类作为基类,派生出了A和B类,其中A和B有从基类CChar继承下来的属性,而且对于A和B有不同的Set_M函数,为了让程序自动找到他要使用的是基类还是自己的Set_M函数,我们可以把基类中的函数定义为虚函数,这样就可以达到我们想要的目的了。

  其中我们定义了一个Set()函数,这个函数内包含了我们需要使用的Set_M()函数,更加体现了多态的性质。

原文地址:https://www.cnblogs.com/coder2012/p/2709876.html