纯虚函数:
- 无法实例化对象;
- 子类必须重写抽象类中的纯虚函数,否则也属于抽象类,则无法实例化对象;
class Base {
public:
virtual void funcPrint() = 0;
};
class Son :public Base {
public:
void funcPrint() {
cout << "调用了子类的func()" << endl;
}
};
int main() {
Base * son = new Son;
son->funcPrint();
system("pause");
return 0;
}
案例引用:制作饮品
class AbstractDrinking {
public:
virtual void Boil() = 0;
virtual void Brew() = 0;
virtual void PourInCup() = 0;
virtual void PutSomething() = 0;
void makeDrink() {
Boil();
Brew();
PourInCup();
PutSomething();
}
};
class Coffee:public AbstractDrinking {
public:
virtual void Boil() {
cout << "煮农夫山泉" << endl;
}
virtual void Brew(){
cout << "冲泡咖啡" << endl;
}
virtual void PourInCup(){
cout << "倒入杯中" << endl;
}
virtual void PutSomething(){
cout << "倒入牛奶" << endl;
}
void makeDrink() {
Boil();
Brew();
PourInCup();
PutSomething();
}
};
void doWork(AbstractDrinking * abs) {
abs->makeDrink();
delete abs;
}
int main() {
doWork(new Coffee);
system("pause");
return 0;
}
虚析构和纯虚析构:
- 多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码;
- 解决方式:将父类中的析构函数改为虚析构或者纯虚析构;
虚析构和纯虚析构共性: 1.可以解决父类指针释放子类对象; 2.都需要有具体的函数实现;
虚析构和纯虚析构区别: 如果纯虚析构,该类属于抽象类,无法实例化对象;
虚析构语法: virtual ~ 类名( ) { }
纯虚析构语法: virtual ~类名( )=0; 类名 : : ~ 类名( ) { }
class Animal {
public:
Animal() {
cout << "Animal的构造函数调用" << endl;
}
virtual ~Animal() {
cout << "Animal的析构函数调用" << endl;
}
virtual ~Animal()=0;
virtual void speak() = 0;
};
Animal::~Animal() {}
class Cat :public Animal {
public:
Cat(string name) {
cout << "cat的构造函数调用" << endl;
c_Name = new string(name);
}
void speak() {
cout <<*c_Name<< "小猫在说话" << endl;
}
string *c_Name;
~Cat(){
if (c_Name != NULL) {
cout << "Cat析构函数调用" << endl;
delete c_Name;
c_Name = NULL;
}
}
};
int main() {
Animal * cat = new Cat("Tom");
cat->speak();
delete cat;
system("pause");
return 0;
}
父类指针在析构时候不会调用子类中析构函数,导致子类如果有堆区属性,出现内存泄露(即无法释放干净内存空间)————这时需要使用虚析构或纯虚析构才可以调用子类的析构函数,释放堆区内存;
总结
- 1.虚析构或纯虚析构就是用来解决通过父类指针释放子类对象;
- 2.如果子类中没有堆区数据,可以不写虚析构或者纯虚析构;
- 3.拥有纯虚析构函数的类也属于抽象类;
|