虚函数的继承与实现
- 父类子类都是虚函数,则实现依旧是在子类。
- 父类的非虚函数中调用虚函数,在子类实现,依旧是按照子类实现的方式执行虚函数
#include <iostream>
#include <string>
using namespace std;
class Animal{
public:
void play(){eat(); shout(); sleep(); }
virtual void eat() {cout << "class Animal eat " << endl;};
virtual void shout(){cout << "class Animal shout " << endl;};
virtual void sleep(){cout << "class Animal sleep " << endl;};
};
class Tiger:public Animal{
public:
virtual void eat() {cout << "class Tiger eat " << endl;};
virtual void shout(){cout << "class Tiger shout " << endl;};
virtual void sleep(){cout << "class Tiger sleep " << endl;};
};
int main(){
Animal* p = NULL;
p = new Tiger;
p->play();
delete p;
getchar();
return 0;
}
虚函数的析构
#include <iostream>
#include <string>
using namespace std;
class Animal{
public:
Animal() {cout << "class Animal " ;shout();}
//重点就是这个析构函数的 virtual
virtual ~Animal(){cout << "class ~Animal " ;shout();}
void play(){eat(); shout(); sleep(); }
virtual void eat() {cout << "class Animal eat " << endl;};
virtual void shout(){cout << "class Animal shout " << endl;};
virtual void sleep(){cout << "class Animal sleep " << endl;};
};
class Tiger:public Animal{
public:
Tiger() {cout << "class Tiger " ;shout();}
~Tiger(){cout << "class ~Tiger " ;shout();}
virtual void eat() {cout << "class Tiger eat " << endl;};
virtual void shout(){cout << "class Tiger shout " << endl;};
virtual void sleep(){cout << "class Tiger sleep " << endl;};
};
int main(){
Animal* p = NULL;
p = new Tiger;
p->play();
delete p;
getchar();
return 0;
}
纯虚函数
不会真正被执行,由子类来执行。有纯虚函数的类成为抽象类。
为了防止抽象类的方法被执行,编译器不允许实例化抽象类对象,但可以使用抽象类的指针或者引用指向子类对象。
virtual void eat() = 0;
虚函数的实现原理
每个类都有一个隐含的虚表
多态原理:父类指针指向虚表中的子类指针,虚表中的指针指向子类的虚函数表,然后通过子类的虚函数表调用子类对象及其内部变量、方法。
父类指针--->虚函数表(VTable)--->子类虚表
#include <iostream>
#include <string>
using namespace std;
class A {
double d;
};
class B : public A{
double d;
public:
void f(){}//普通函数在代码区,不占用类的存储空间
};
class C{
double d;
public:
virtual void f(){cout << " class C " << endl;}
virtual void g(){cout << this << " " << &d << endl;}
virtual void h(){}
virtual void i(){}
virtual void j(){}
};
class D : public C{
double d;
public:
virtual void f(){cout << " class D " << endl;}
};
int main(){
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
cout << sizeof(C) << endl;
cout << sizeof(D) << endl;
A* p = new B;
C* q1 = new C;
C* q2 = new D;
q1->f();
q2->f();
q1->g();
q2->g();
cout << "======================" << endl;
//通过指针赋值改变虚表中的指向关系
//让q2所指对象的虚表指针指向C类虚函数表
memcpy(q2, q1, 8);
q1->f();
q2->f();
getchar();
return 0;
}