参考文章:虚函数–https://blog.csdn.net/LC98123456/article/details/81143102
C++的多态性用一句话概括就是:
在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。
如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数,当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态(记住:是动态!)的调用属于子类的该函数。
我们先来看一段代码
#include
class People{
public:
People()
{
std::cout << "People" << std::endl;
}
~People()
{
std::cout << "~People" << std::endl;
}
void doWork(){
std::cout << "打豆豆" << std::endl;
}
};
class Student : public People{
public:
void doWork(){
std::cout << "打游戏" << std::endl;
}
};
class Worker : public People{
public:
void doWork(){
std::cout << "搬砖" << std::endl;
}
};
int main()
{
// 基类指针
People *peo;
// 指向基类对象
peo = new People;
peo->doWork();
delete peo;
// 指向子类对象
peo = new Student;
peo->doWork();
delete peo;
peo = new Worker;
peo->doWork();
delete peo;
getchar();
return 0;
}
注:
可以用基类指针指向子类对象,但不可以反过来,即 Student* stu = new People; 是错的;
我们做一点的转化
int main()
{
// 基类指针
People *peo;
peo = new People;
Student* stu;
// 强转
stu = (Student*) peo;
stu->doWork();
delete stu;
getchar();
return 0;
}
函数隐藏状态下,不关心指针存的是谁的地址,而关心指针类型,指针类型是啥,调用啥的成员函数,即People* 类型指针,调用 People的成员函数,Student* 调用 Student的成员函数,与 new 的对象无关;
为了方便使用多态特性,我们常常需要在基类中定义虚函数
#include
class People{
public:
People()
{
std::cout << "People" << std::endl;
}
~People()
{
std::cout << "~People" << std::endl;
}
// 虚函数
virtual void doWork(){
std::cout << "打豆豆" << std::endl;
}
};
class Student : public People{
public:
// 函数覆盖/函数重写
void doWork(){
std::cout << "打游戏" << std::endl;
}
};
int main()
{
People* peo;
peo = new Student;
peo->doWork();
delete peo;
peo = new People;
peo->doWork();
delete peo;
getchar();
return 0;
}
#include
class People //抽象类{
public:
virtual void doWork() = 0; //纯虚函数
};
class Student : public People{
public:
void doWork()//如果子类不重写父类的虚函数,那么这个子类也是抽象类
{
std::cout << "打王者荣耀" << std::endl;
}
};
int main()
{
People p;//不允许实例化
Student s;//子类可以实例化
getchar();
return 0;
}
常常把析构函数设置成虚函数
先来看一段代码&结果
#include
class People{
public:
People()
{
std::cout << "People" << std::endl;
}
~People()
{
std::cout << "~People" << std::endl;
}
void doWork() = 0;
};
class Student : public People{
public:
Student()
{
std::cout << "People" << std::endl;
}
~Student()
{
std::cout << "~People" << std::endl;
}
virtual void doWork(){
std::cout << "打游戏" << std::endl;
}
};
int main()
{
People* peo = new Student;
peo->doWork();
delete peo;
getchar();
return 0;
}
显然我们发现,在基类指针指向派生类对象后,在释放空间时,不会走派生类的析构函数;(当派生类指针只想自己的对象时,会调用派生类的析构)
把基类析构函数设置成虚函数
class People{
public:
People()
{
std::cout << "People" << std::endl;
}
virtual ~People()
{
std::cout << "~People" << std::endl;
}
void doWork() = 0;
};
为什么要加虚析构,会有问题吗? 基类指针指向派生类对象后,基类的析构函数不定义成虚函数,在释放内存时,派生类的析构函数不会被调用,如果在派生类的析构函数里面有释放资源的操作,那么就会造成资源的泄露;
为什么默认不是虚析构 虚函数?会在类中产生一个虚指针,浪费空间。
https://www.cnblogs.com/hushpa/p/5707475.html
https://blog.csdn.net/qq_36359022/article/details/81870219
http://c.biancheng.net/cpp/biancheng/view/243.html