虚函数
简单地说,那些被virtual关键字修饰的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异而采用不同的策略。
如果父类的函数(方法)根本没有必要或者无法实现,完全要依赖子类去实现的话,可以把此函数(方法)设为virtual 函数名=0 我们把这样的函数(方法)称为纯虚函数。 例virtual void print()=0;
class A{
public:
void print(){ cout<<"This is A"<<endl;}
};
class B:public A{
public:
void print(){ cout<<"This is B"<<endl;}
};
int main()
{
A a;
B b;
a.print();
b.print();
}
输出
This is A
This is B
多态还有个关键之处就是用指向基类的指针或引用来操作对象(多态性是将接口与实现进行分离,单接口)
int main()
{
A a;
B b;
A* p1=&a;
A* p2=&b; //由于是父子类 可以安全的传递指针 否则需要强转换
p1->print();
p2->print();
}
输出
This is A
This is A
以上代码改写一步: virtual void print(){ cout<<"This is A"<<endl;}
输出
This is A
This is B
虚函数的实现
由于类中有虚函数存在,所以编译器就会为类插入一段数据,并创建一个表。
那段数据叫做vptr指针,指向那个表。那个表叫做vtbl,每个类都有自己的vtbl,vtbl的作用就是保存自己类中虚函数的地址,
分析下面的代码
A *p=new A;
p->print();
首先是取出vptr的值,这个值就是vtbl的地址,再根据这个值来到vtbl这里,由于调用的函数A::print()是一个虚函数,所以取出vtbl里的值,这个值就是A::print()的地址了,最后调用这个函数。
现在我们可以看出来了,只要vptr不同(基类和派生类有不同的vptr),指向的vtbl就不同,而不同的vtbl里装着对应类的虚函数地址,所以这样虚函数就可以完成它的任务。
http://baike.baidu.com/view/161302.htm
虚基类
虚基类的基本原则是在内存中只有基类成员的一份拷贝。这样,通过把基类继承声明为虚拟的,就只能继承基类的一份拷贝,从而消除歧义。用virtual限定符把基类继承说明为虚拟的。
在派生类继承基类时,加上一个virtual关键词则为虚拟基类继承
虚基类主要解决在多重继承时,基类可能被多次继承,虚基类主要提供一个基类给派生类
浙公网安备 33010602011771号