一 多态的语法
多态的基本含义是,函数参数父为类型,传入该类不同的子类,所表现的行为会根据子类的具体情况而不同,大家请看代码:
#include<iostream>
using namespace std;
class Animal {
public:
void eat() {
cout << "Animal eat" << endl;
}
};
class Cat:public Animal{
public :
void eat() {
cout << "Cat eat" << endl;
}
};
void Test(Animal &a) {
a.eat();
}
int main() {
Cat c;
Test(c);
return 0;
}
我们在传入Cat类的对象c时会隐式转换为父类Animal类型,上述代码运行结果如下:
并不符合预期,那我们要怎么做才能实现多态呢?
很简单,在父类同名函数前加上一个关键字 virtual 其中原理马上就讲:
#include<iostream>
using namespace std;
class Animal {
public:
virtual void eat() {
cout << "Animal eat" << endl;
}
};
class Cat:public Animal{
public :
void eat() {
cout << "Cat eat" << endl;
}
};
void Test(Animal &a) {
a.eat();
}
int main() {
Cat c;
Test(c);
return 0;
}
运行结果如下:
二 虚函数
先请大家对比两端代码:
#include<iostream>
using namespace std;
class Animal {
public:
void eat() {
cout << "Animal eat" << endl;
}
};
class Cat:public Animal{
public :
void eat() {
cout << "Cat eat" << endl;
}
};
void Test(Animal &a) {
a.eat();
}
int main() {
cout << sizeof(Animal) << endl;
return 0;
}
#include<iostream>
using namespace std;
class Animal {
public:
virtual void eat() {
cout << "Animal eat" << endl;
}
};
class Cat:public Animal{
public :
void eat() {
cout << "Cat eat" << endl;
}
};
void Test(Animal &a) {
a.eat();
}
int main() {
cout << sizeof(Animal) << endl;
return 0;
}
第一段代码运行结果如下:
说明成员函数并不存储于类内部,而为了避免我们因此无限制的定义类所以将其内存长度设置为1
第二段代码运行结果如下:
大家应该知道,在C++中long long ,double, 指针三种类型的变量其内存长度为8,在这里只可能是指针变量,大家可以明白了,类内存储的本质是一个函数指针,更准确地来说是虚函数指针数组,数组中每一个元素都是一个指向虚函数的指针,如果子类与父类有同名函数且父类中声明该函数为虚函数,则会用子类函数覆盖掉父类中虚函数指针的相应位置的元素 。
大家再看两段代码感受一下:
#include<iostream>
using namespace std;
class Animal {
public:
virtual void eat() {
cout << "Animal eat" << endl;
}
void sleep() {
cout << "Animal sleep" << endl;
}
};
class Cat:public Animal{
public :
void eat() {
cout << "Cat eat" << endl;
}
void sleep() {
cout << "Cat sleep" << endl;
}
};
void Test(Animal &a) {
a.eat();
a.sleep();
}
int main() {
Cat c;
Test(c);
return 0;
}
#include<iostream>
using namespace std;
class Animal {
public:
virtual void eat() {
cout << "Animal eat" << endl;
}
virtual void sleep() {
cout << "Animal sleep" << endl;
}
};
class Cat:public Animal{
public :
void eat() {
cout << "Cat eat" << endl;
}
void sleep() {
cout << "Cat sleep" << endl;
}
};
void Test(Animal &a) {
a.eat();
a.sleep();
}
int main() {
Cat c;
Test(c);
return 0;
}
第一段代码运行结果如下:
第二段代码运行结果如下:
三 纯虚函数和抽象类
如果一个虚函数没有实现则就是纯虚函数
如果父类里有纯虚函数则就是抽象类
抽象类无法实例化对象,抽象类就是为了被继承,在子类中实现虚函数。
#include<iostream>
using namespace std;
class Animal {
public:
virtual void eat() = 0;
};
int main() {
return 0;
}
像这样,eat()就是一个纯虚函数,Animal就是一个纯虚类。
举一个具体的例子:
#include<iostream>
using namespace std;
class Animal {
public:
virtual void eat() = 0;
};
class Cat {
public:
void eat() {
cout << "Cat eat" << endl;
}
};
int main() {
Cat c;
c.eat();
return 0;
}
稍微变一下:
#include<iostream>
using namespace std;
class Animal {
public:
virtual void eat() = 0;
};
class Cat {
public:
virtual void eat() {
cout << "Cat eat" << endl;
}
};
class BossCat {
public:
void eat() {
cout << "BossCat eat" << endl;
}
};
int main() {
BossCat c;
c.eat();
return 0;
}
Cat中也定义了虚函数,Cat中的虚函数本身实现了父类Animal中的纯虚函数,同时又让Cat的子类能够重写它的这个虚函数。
四 虚析构和纯虚析构
父类类型的指针指向子类对象,如果父类中的析构函数没有加上virtual那么在销毁时就不会调用子类的析构函数就会发生内存泄漏。
请看代码:
#include<iostream>
using namespace std;
class Base {
public:
Base() {}
~Base() {
cout << "Base 析构" << endl;
}
};
class Son:public Base{
public:
int* m_data;
Son(): m_data(NULL){
m_data = new int(10);
}
~Son() {
delete m_data;
cout << "Son析构" << endl;
}
};
int main() {
Base* base = new Son();
delete base;
return 0;
}
运行结果如下:
对比一下:
#include<iostream>
using namespace std;
class Base {
public:
Base() {}
virtual ~Base() {
cout << "Base 析构" << endl;
}
};
class Son:public Base{
public:
int* m_data;
Son(): m_data(NULL){
m_data = new int(10);
}
~Son() {
delete m_data;
cout << "Son析构" << endl;
}
};
int main() {
Base* base = new Son();
delete base;
return 0;
}
运行结果如下:
上述是虚析构,下面我们来看看纯虚析构:
#include<iostream>
using namespace std;
class Base {
public:
Base() {}
virtual ~Base() = 0;
};
Base::~Base() {
cout << "Base 析构" << endl;
}
class Son:public Base{
public:
int* m_data;
Son(): m_data(NULL){
m_data = new int(10);
}
~Son() {
delete m_data;
cout << "Son析构" << endl;
}
};
int main() {
Base* base = new Son();
delete base;
return 0;
}
大家要注意,纯虚析构要在类外部实现,还有定义为纯虚析构则该类就是抽象类不能实例化对象,这里使用指针并不违背。运行结果与虚析构函数相同。
本文就讲到这里,还望大家多多支持与指正!
标签:函数,每天,多态,C++,public,Animal,using,include,class From: https://blog.csdn.net/2301_79024503/article/details/142755111