1. 基类的指针
因当创建一个类的对象时会创建它的父类对象.如下代码:
class Animal {
public:
int num;
};
class Human : public Animal {
public:
int ret;
};
class MM : public Human {
};
Animal *a = new MM; //基类的指针指向派生类对象
Human *h = new MM; //父类的指针指向子类对象.
因父类/基类是比子类/派生类的空间小,所以基类的指针可以指向它的派生类的对象.
派生类的指针不可以指向父类/基类的对象,因派生类指针可访问的范围大
2. 通过父类指针回收子类对象空间的问题.
class Animal {
public:
Animal() {
cout << "animal init" << endl;
}
~Animal() {
cout << "animal exit" << endl;
}
};
class Human : public Animal {
private:
int *data;
public:
Human() {
data = new int[1024];
cout << "human init " << endl;
}
~Human() {
delete [] data;
cout << "human exit " << endl;
}
};
int main(void)
{
Animal *a = new Human;
delete a;
return 0;
}
编译执行后的输出:
[root@localhost 12multi-stats]# ./a.out
animal init
human init
animal exit
发现通过父类指针回收子类对象时子类的析构函数没有得到触发.
解决这个问题,只要把基类的构造函数声明为virtual函数.通常情况下,基类的析构函数都是声明为虚函数的.
3. 函数重写
如下面,父类子类都实现了一个eat函数,当通过子类对象来调用函数时,使用子类里的函数。但父类的函数也是存放的,也可以指定调用父类里的函数.
using namespace std;
class Animal {
public:
void eat() {
cout << "animal eat" << endl;
}
};
class Human : public Animal {
public:
void eat() {
Animal::eat(); //指定调用父类里的函数
cout << "human eat" << endl;
}
};
int main(void)
{
Human h;
h.eat();
h.Animal::eat(); //指定调用父类里的eat函数
return 0;
}
4. 虚函数的作用
class Animal {
public:
void eat() {
cout << "animal eat" << endl;
}
};
class Human : public Animal {
public:
void eat() {
cout << "human eat" << endl;
}
};
int main(void)
{
Animal *a = new Human;
a->eat();
return 0;
}
当代码执行时,会发现调用的其实是父类的eat函数,但从合理来说,父类指针指向的是子类的对象,应是调用子类重新实现的函数.要想调用到子类新实现的函数,只需把父类里的同名函数声明为virtual即可.
虚函数的作用就是通过基类指针提供一种方法,可以调用到派生类里新实现的函数功能。实现代码往后兼容的目的。也是可以实现先写好框架,这框架不管后面怎样的扩展,都可以不用改变的.
虚函数是函数体,纯虚函数其实就没有函数体的虚函数.用于指定派生类里必须要实现的函数.
纯虚函数:
class Animal {
public:
virtual void eat() = 0;
}
5. 多类其实就是使用虚函数实现的功能.
例如,写个游戏的副本:
class Role {
public:
virtual void attack() = 0;
virtual void jump() = 0;
void play() { //游戏副本:跳, 跳 , 杀, 跳
jump();
jump();
attack();
jump();
cout << "###################" << endl;
}
};
写好副本后,不管什么样的角色,只要继承了Role,实现虚函数,当调用play进入副本时都可以得到调用.
而且不管继承多少层,都是可以兼容的
class Magician : public Role {
public:
void attack() {
cout << "magician attack" << endl;
}
void jump() {
cout << "magician jump" << endl;
}
};
class Knight : public Role {
public:
void attack() {
cout << "knight attack" << endl;
}
void jump() {
cout << "kngiht jump" << endl;
}
};
class SuperKnight : public Knight {
public:
void attack() {
cout << "super knight attack" << endl;
}
void jump() {
cout << "super kngiht jump" << endl;
}
};
int main(void)
{
SuperKngiht sk;
sk.play();
Magician m;
m.play();
return 0;
}