您的位置:首页 > 编程语言 > C语言/C++

C++ 中的Virtual关键字与多态

2016-08-01 00:00 169 查看
//
// [什么是Virtual Table]
//


在类成员函数前添加virtual关键字,该函数就是虚函数。
编译后,虚函数们保存在类中的一个数组里,叫做虚表(Virtual Table)

用含有虚表的类生成对象,对象的内存中就存在一个指向该类虚表的指针(虚指针)
这样使用虚函数时,即可通过对象中的虚指针来调用了

当子类继承存在虚表的父类时,父类的虚表也会被copy进子类中
当子类存在与父类的虚函数同名函数时,则子类中的该函数将会覆盖掉继承自父类的虚表中的同名函数,以此来实现对象的多态性

1:虚表编译后就被创建了
2:虚指针只有在对象创建时才被创建


//
// [开始测试]
//


class Animal
{
public:
Animal() { puts("Animal"); }
virtual ~Animal() { puts("~Animal"); }

virtual void eat() {puts("Animal::eat");}
};

class Dog : public Animal
{
public:
Dog() {puts("Dog");}
~Dog() {puts("~Dog");}

void eat() {puts("Dog::eat");}
};

void test()
{
Animal* a = new Dog;
a->eat();
delete a;
}

/*
这里执行 a->eat(); 后,子类的eat()已经覆盖掉了虚表中继承自中父类的eat()
所以可以正常执行子类的eat()
*/
//结果:执行test后
//Animal
//Dog
//Dog::eat
//~Dog
//~Animal

/*
这里如果基类Animal不加virtual的话
执行 a->eat(); 只是去执行一段Animal中的正常函数
*/
//结果:执行test后
//Animal
//Dog
//Animal::eat
//~Animal

// //[抽象类] //

class Animal
{
public:
Animal() { puts("Animal"); }
virtual ~Animal() { puts("~Animal"); }

//这里定义eat()为纯虚函数 virtual xxx = 0
//带有纯虚函数的类为抽象类,无法被实例化
//继承类必须覆盖该函数的声明
//如果尝试实例化 new Animal;   编译器会提示错误 [“Animal”: 不能实例化抽象类]
virtual void eat() = 0;
};

//继承后仍为抽象类
class Dog : public Animal
{
public:
Dog() {puts("Dog");}
~Dog() {puts("~Dog");}

virtual void eat() =0;
};

//博美犬继承并实现了抽象类Dog
//可以被实例化
class Pomeranian  : public Dog
{
public:
Pomeranian () {puts("Pomeranian ");}
~Pomeranian () {puts("~Pomeranian ");}

virtual void eat()  {puts("Pomeranian :eat");}
};

void test()
{
Animal* a = new Pomeranian;
a->eat();
delete a;
}

//结果:test执行之后
//Animal
//Dog
//Pomeranian
//Pomeranian:eat
//~Pomeranian
//~Dog
//~Animal
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: