多态
多态分为:静态多态(函数重载,运算符重载)和动态多态(派生类、虚函数)
二者区别:静态多态是在地址编译时绑定,而动态多态是在地址运行时绑定
动态多态的特点:
1.有继承关系
2.子类重写父类虚函数(就是跟父类行为函数名称一样,但是是作为子类的行为)
动态多态的调用:
父类指针或引用指向子类对象(简单来说就是创建父类传参函数,下面再添加子类对象,让子类对象传入进去即可)
#include<iostream>
using namespace std;
class Animal
{
public:
virtual void speaking()
{
cout<<"Animal Speaking"<<"\n";
}
};
class Dog:public Animal
{
public:
void speaking()
{
cout<<"Dog Speaking"<<"\n";
}
};
//地址早就绑定好了,在编译阶段就确定了地址
//父类指针写法
// void Animal1(Animal *a)
// {
// a->speaking();
// }
//父类引用写法
void Animal1(Animal &ani)
{
ani.speaking();
}
void test()
{
Dog g;
//指针写法: Animal1(&g);
//引用写法
Animal1(g);
}
int main()
{
test();
return 0;
}
小小彩蛋:今天女神节于是我来给各位女神写一份多态简易测试代码!
#include<iostream>
#include<string>
using namespace std;
class Mom
{
public:
virtual void Festival()
{
cout<<"Happy women's Day"<<"\n";
}
};
class Daughter : public Mom
{
public:
void Festival()
{
cout <<"Happy Goddesses'Day"<<"\n";
}
};
//引用写法
// void Festival1(Mom &M)
// {
// M.Festival();
// }
//指针写法
void Festival1(Mom *M)
{
M->Festival();
}
void solve()
{
Daughter Alaso_shuang;
Festival1(&Alaso_shuang);
}
int main()
{
solve();
return 0;
}
运算器多态实例
#include <iostream>
#include <string>
using namespace std;
class Cal
{
public:
virtual int Yunsuan()
{
return 0;
}
public:
int m_A;
int m_B;
};
class Plus : public Cal
{
public:
int Yunsuan()
{
return m_A + m_B;
}
};
class Sub : public Cal
{
public:
int Yunsuan()
{
return m_A - m_B;
}
};
class mul : public Cal
{
public:
int Yunsuan()
{
return m_A * m_B;
}
};
class chu : public Cal
{
public:
int Yunsuan()
{
return m_A / m_B;
}
};
void solve()
{
Cal *p = new Plus;//注意是父类的指针指向子类对象啊!
p->m_A = 10;
p->m_B = 20;
cout << p->m_A << "+" << p->m_B << "=" << p->Yunsuan() << "\n";
delete p;//注意是把堆区的数据给释放了,接下来的p->m_A 和 p->m_B的数据为空
p = new Sub;
p->m_A = 20;
p->m_B = 10;
cout << p->m_A << "-" << p->m_B << "=" << p->Yunsuan() << "\n";
delete p;
p = new mul;
p->m_A = 20;
p->m_B = 10;
cout << p->m_A << "*" << p->m_B << "=" << p->Yunsuan() << "\n";
delete p;
p = new chu;
p->m_A = 18800;
p->m_B = 10;
cout << p->m_A << "/" << p->m_B << "=" << p->Yunsuan() << "\n";
}
int main()
{
solve();
return 0;
}
纯虚函数和抽象类
提要点:
1.纯虚函数语法:virtual 函数返回类型 函数名(参数) = 0;
2.类中一旦有成员函数就被称为抽象类
3.抽象类的特点:无法实例化对象(创建一个对象会出现报错),子类必须重写父类的纯虚函数否则属于抽象类,无法创建对象
#include<iostream>
using namespace std;
class F
{
public:
//纯虚函数写法
virtual void f() = 0;
};
class son1 : public F
{
public:
virtual void f()
{
cout<<"Hello,world"<<"\n";
}
};
void solve()
{
F *son = new son1; //开始没有重写父类纯虚函数,提示不允许使用抽象类类型 "son" 的对象
son->f();
delete son;
}
int main()
{
solve();
return 0;
}
纯虚函数实例二:制作简易奶茶和茶叶
#include<iostream>
using namespace std;
class YinPin
{
public:
virtual void Chongpao() = 0;
virtual void JiaoBan() = 0;
virtual void DaoLiao() = 0;
virtual void BaoZhuang() = 0;
void MakeYinpin()
{
Chongpao();
JiaoBan();
DaoLiao();
BaoZhuang();
}
};
class NaiCha : public YinPin
{
public:
void Chongpao()
{
cout<<"add Water!"<<"\n";
}
void JiaoBan()
{
cout<<"DaoGu"<<"\n";
}
void DaoLiao()
{
cout<<"Push in it"<<"\n";
}
void BaoZhuang()
{
cout<<"FengZhuang"<<"\n";
}
};
class ChaYe : public YinPin
{
public:
void Chongpao()
{
cout<<"add heat Water!"<<"\n";
}
void JiaoBan()
{
cout<<"JiaoJiaoJiao"<<"\n";
}
void DaoLiao()
{
cout<<"throw it"<<"\n";
}
void BaoZhuang()
{
cout<<"BaoBaoBao"<<"\n";
}
};
void solve()
{
YinPin *Y = new NaiCha;
Y->MakeYinpin();
delete Y;
Y = new ChaYe;
Y->MakeYinpin();
delete Y;
}
int main()
{
solve();
return 0;
}
虚析构和纯虚析构
提要点:
纯虚析构和虚析构都是为了让在父类指针指向子类对象的堆区数据释放
不同点:
虚析构:直接写声明和实现即可
纯虚析构:需要在类内写声明,内外写实现(记得加上父类作用域)
//纯虚析构和虚析构都是为了在父类指针指向子类对象的堆区数据释放
//不同点:
//虚析构:直接写声明和实现即可
//纯虚析构:需要在类内写声明,内外写实现(记得加上父类作用域)
//纯虚析构和虚析构都是为了在父类指针指向子类对象的堆区数据释放
//不同点:
//虚析构:直接写声明和实现即可
//纯虚析构:需要在类内写声明,内外写实现(记得加上父类作用域)
#include<iostream>
#include<string>
using namespace std;
class Animal
{
public:
virtual void Jiao() = 0;
//虚析构写法
// virtual ~Animal()
// {
// cout<<"Animal xigoufunction"<<"\n";
// }
//纯虚析构写法
virtual ~Animal() = 0;
};
Animal::~Animal()
{
cout<<"Animal xigoufunction"<<"\n";
}
class Dog : public Animal
{
public:
void Jiao()
{
cout<<"Wolf Wolf"<<"\n";
}
Dog(string name)
{
m_Name = new string(name);//开一个新的空间定义为string类型的name
}
//如果没有虚析,下面这段析构狗子类的代码不可能会执行,因为我开了个堆区的数据
//解决方案:写一个虚析构
~Dog()
{
cout<<"DogxigouFunction"<<"\n";
if(this->m_Name != NULL)
{
delete m_Name;
m_Name = NULL;
}
}
string *m_Name;
};
void test()
{
Animal *An = new Dog("WangCai");
An->Jiao();
delete An;
}
int main()
{
test();
return 0;
}