1>静态联编,动态联编
将源代码中的函数调用解释为执行特定的函数代码块被称为函数名联编
在C语言中,没有函数的重载,所以,在编译过程中就可以完成函数的联编,这种叫静态联编。
而C++中,虚函数的使用,使得在编译过程中我们无法得知使用的是哪一个,所以编译器 只能在程序运行时选择正确的虚函数代码,这种叫动态联编。
2> 虚函数的工作原理
编译器处理虚函数的方法: 给每个对象添加一个隐式的成员,成员中保存了一个指向函数地址数组的指针,这种数组称为,虚函数表,虚函数表存储的是为类对象进行声明的虚函数地址。
3>注意 :
1)如果要用指向对象的引用或指针来调用虚方法,程序将使用为对象类型定义的方法。
就比如:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
class A{
public:
virtual void get()
{
cout<<"Hello world"<<endl;
}
};
class B : public A{
public :
void get()
{
cout<<"B"<<endl;
}
};
int main()
{
A * a;
B b;
a = &b;
a->get();
}
这样的话输出的是B;
2) 构造函数不能是虚函数,创建派生类对象是,将调用派生类的构造函数,而不是基类的构造函数,然后,派生类的构造函数将使用基类的构造函数。
3) 析构函数,如果类要是基类的话应当是虚函数。
驾驶额Empoyee是基类,Singer是派生类,并添加一个char *成员,该成员是指向有new分配的内存。当Singer过期的时候,移动会调用~Singer()析构函数来释放内存:
那么
Employee *pe = new String;
。。。
delete pe;
这时候调用的是 ~Employee()析构函数,释放由Singer对象中Employee部分指向的内存,但不会释放新的类成员指向的内存。
但是如果析构函数是虚拟的话,则上述代码先调用 ~Singer析构函数;
4> 友元函数不能是虚函数,因为友元函数不是类成员。
5>如果重新定义继承的方法,应确保与原来的原型完全相同,但如跟返回值类型是基类引用或者指针的时候,则可以修改为指向派生类的引用或指针, 称为返回类型协变。