----纯虚函数的声明: virtual 函数声明 = 0
1.只有声明,没有实现体 = 0仅仅只是语法表现形式
2.含有纯虚函数的类 叫抽象基类 不能实例化(不能生成对象)
3.仅仅是为了提供族类的接口 java 中 称此种类为 Interface
4.如果子类中没有覆写纯虚函数,那子类也为抽象基类 也不能实例化
5.如果子类只是把父类的纯虚函数原封不动拿到内部声明,语法也通不过,拿下来就必须覆写,要不然就不拿(最新版本的c++支持把父类的纯虚函数原封不动拿到内部声明)
----析构函数声明为virtual(虚析构):
继承时,要养成的一个好习惯就是,基类析构函数中,加上virtual。
使用情况:
即使没有虚函数的类,也可能产生父类指针指向子类对象的情况(多态),在这种情况下,父类的析构函数要声明为虚析构。凡是含有虚函数的类,析构函数也应该声明为虚函数,才可以实现完整的析构。delete 父类的指针,要实现同时调用父子类的析构,不虚的话只调用了父类的析构函数。
原因:
可以将子类对象的地址赋值给父类指针,也就是说父类指针可以指向子类的对象(多态性),如果删除该父类指针delete []p;就会调用该指针指向的子类析构函数,而子类的析构函数又自动调用父类的析构函数,这样整个派生类的对象完全被释放。如果父类的析构函数不被声明成虚函数,则编译器实施静态绑定,虚函数是动态绑定的基础,因此现在不会发生动态绑定,指针的类型为父类指针,在删除父类指针时,只会调用父类的析构函数而不调用子类析构函数,这样就会造成子类对象析构不完全。造成内存泄漏,所以,将析构函数声明为虚函数是十分必要的。
其他文章:https://www.cnblogs.com/liushui-sky/p/5824919.html
----成为虚函数的限制:
1)只有类的成员函数才能声明为虚函数,虚函数仅适用于有继承关系的类对象,所以普通函数不能声明为虚函数。
2)静态成员函数不能是虚函数,静态成员函数不受对象的捆绑,只有类的信息。
3)内联函数不能是虚函数
4)构造函数不能是虚函数,构造时,对象的创建尚未完成。构造完成后,才能算一个名符其实的对象。构造函数同时承担着虚函数表的建立,没有对象的时候,虚函数没有意义
5)析构函数可以是虚函数且通常声明为虚函数
主函数:
#include "stdafx.h"
#include <iostream>
using namespace std;
#include "Dog.h"
#include "Cat.h"
int _tmain(int argc, _TCHAR* argv[])
{
//Dog g;
g.voice();
//Cat c;
c.voice();
//Animal *pa = &g;
//pa->voice();
//pa = &c;
//pa->voice();
//Animal a; 抽象基类不能实例化
cout << "==================" << endl;
Animal* p = new Dog;
p->voice();
delete p;
//p = new Cat;
//p->voice();
return 0;
}
Animal.h
#pragma once
#include <iostream>
using namespace std;
class Animal
{
public:
Animal();
virtual ~Animal(); //需要加virtual实现完整的析构
virtual void voice() = 0; //纯虚函数
};
Animal.cpp
#include "Animal.h"
Animal::Animal()
{
cout << "Animal::Animal()" << endl;
}
Animal::~Animal()
{
cout << "Animal::~Animal()" << endl;
}
Dog.h
#pragma once
#include <iostream>
using namespace std;
#include "Animal.h"
class Dog:public Animal
{
public:
Dog();
virtual ~Dog();
virtual void voice();
};
Dog.cpp
#include "Dog.h"
Dog::Dog()
{
cout << "Dog::Dog()" << endl;
}
Dog::~Dog()
{
cout << "Dog::Dog()" << endl;
}
void Dog::voice()
{
cout << " wang wang wang wang " << endl;
}
Cat.h
#pragma once
#include <iostream>
using namespace std;
#include "Animal.h"
class Cat:public Animal
{
public:
Cat();
virtual ~Cat();
virtual void voice();
};
Cat.cpp
#include "Cat.h"
Cat::Cat()
{
cout << "Cat::Cat()" << endl;
}
Cat::~Cat()
{
cout << "Cat::~Cat()" << endl;
}
void Cat::voice()
{
cout << " miao miao miao miao " << endl;
}