一.多态: 什么是多态???
一个对象,作用于不同的事物,得到的结果不一样 -- 多态
"一个函数可以实现多种不同的功能"
作用: 提高代码的复用性
静态多态:
在程序编译的时候,已经确定要执行的状态 -- 函数重载
动态多态:
在程序运行的时候,才能确定执行的状态, 根据用户传入不同的对象, 执行不同的状态
多态实例:
C++ #include <iostream> using namespace std; /* 有一个人, 他有工作 工作内容是什么??? 不知道 -- 不了解是什么工作 */ // 人 类 class Person { public: virtual void work(){ cout << "这个人具体工作不详,不知道是干啥的" << endl; } }; //职业 //警察 class Police : public Person{ public: void work(){ cout << "抓小偷,找孩子" << endl; } }; //老师 class Teacher : public Person{ public: void work(){ cout << "讲课,留作业" << endl; } }; //医生 class Doctor : public Person{ public: void work(){ cout << "看病,开药" << endl; } }; //定义一个工作接口 void do_work(Person * p){ p->work(); } int main(int argc, char const *argv[]) { //传入不同参数 -- 作用于不同的类 得到不同的对象 调用不同的work接口 do_work(new Person); do_work(new Police); do_work(new Teacher); do_work(new Doctor); // 一个do_work函数接口, 作用于不同的事物(参数--不同的类) 得到的结果不一样 return 0; } |
实现动态多态的条件:
- 把派生类的对象 赋值 给基类的指针或者引用, 通过基类调用被重写的接口
二.虚析构
语法:
virtual ~析构函数(){}
举例:
C++ virtual ~new_base(){} #include <iostream> using namespace std; class base { public: base(){ cout << "执行base的构造函数" << endl; } virtual ~base(){ cout << "~执行base的析构函数" << endl; } }; class new_base : public base { char * p; public: new_base(){ cout << "执行new_base的构造函数" << endl; p = new char[1024]; cout << "分配1024大小的内存空间" << endl; } virtual ~new_base(){ cout << "~执行new_base的析构函数" << endl; delete []p; cout << "释放1024大小的内存空间" << endl; } }; //定义一个工作接口 // void test(base * p){ // delete p; // } int main(int argc, char const *argv[]) { // 基类指针 指向 派生类堆空间 // 系统无法调用派生类的析构函数 // 会导致无法释放派生类中分配的空间(无法释放派生类中的数据成员) // 内存泄漏 资源浪费 base * q = new new_base; delete q; return 0; } |
总结: 对于析构函数而言, 无论是否用到多态技术, 最好在析构函数前都加上virtual设置为虚析构, 可以万无一失,保证派生类中数据成员会被释放
关于五一作业中的问题:
组合: 一个类中包含了另一个类的对象作为其成员变量,而不是继承了一个类
作用: 提高代码的复用性
私有继承和组合的区别:
1 关系:
私有继承的关系: 两个类是同一个 --两个类之间有关系
私有继承意味着派生类继承了基类的所有成员和方法,但这些成员和方法在派生类外部是不可见的,即它们被隐藏起来,只能通过派生类的接口来访问。
它通常用于表示“是一个”的关系,但这种关系不希望被外部代码所知晓或利用。
组合关系: 一个类里有一个其他类 -- 两个类之间没有任何关系,彼此独立
组合是指一个类包含另一个类的实例作为其成员变量,从而实现功能的复用。拥有者类通过包含其他类的对象来实现某些功能,而不是通过继承获得。当需要将一个类的功能嵌入到另一个类中,并且希望保持这两个类的独立性时,通常会采用组合。这有助于降低类之间的耦合度,并提高代码的可维护性。
C++ #include <iostream> using namespace std; extern "C"{ #include <string.h> } |
/*
根据下面的要求,完成程序编写,要求包含main函数并在main中使用所定义类的对象。
1)定义一个日期类Date,包含年、月、日;
2)定义一个人事管理的Person类,要求包含身份证号pid、出生日期birthday、性别sex、
姓名name、通讯地址address等属性。其中出生出生日期是日期类的对象;
3)要求Date有构造函数(带默认参数)、显示属性函数showDate();Person有构造函数
(带默认参数)、显示属性函数showPerson()。
*/
C++ class Date { public: Date(int y=2024,int m=5,int d=6):year(y),month(m),day(d){} void showDate(){ cout << year << "年" << month << "月" << day << "日" << endl; } int year; int month; int day; }; class Person { public: Person(Date d = 0, int pid = 123456, char sex = 'M',const char *name = "ZQ",const char * add = "沈阳"):birthday(d),pid(pid),sex(sex){ strcpy(this->name,name); strcpy(this->add,add); } void showPerson(){ cout << this->pid << endl; cout << this->name << endl; //直接调用另一个类的对象的函数接口 this->birthday.showDate() ; cout << this->sex << endl; cout << this->add << endl; } Date birthday; int pid; char sex; char name[40]; char add[1024]; }; int main(int argc, char const *argv[]) { Date dd(2000,8,8); dd.showDate(); // Person p(dd); Person p(dd,2201061,'F',"suquan","漠河"); p.showPerson(); return 0; } |
三.纯虚函数 与 抽象类
1.纯虚函数的定义:
virtual 函数返回值类型 函数名(参数) = 0;
举例:
virtual void func() = 0; //纯虚函数
2.抽象类
定义: 如果一个类中有纯虚函数, 那么他就是抽象类
抽象类的特点: 抽象类不能实例化 (定义对象)
抽象类: 只能想象 不能实际得到这个对象
C++ #include <iostream> using namespace std; class Animals{ public: // 纯虚函数 //定义叫声 virtual void say() = 0; }; // 拥有一个纯虚函数 此时就是抽象类 //派生类 -- 对抽象类进行实例化 class dog : public Animals { public: void say(){ cout << "汪汪汪....." << endl; } }; class cat : public Animals { public: // void say(){ // cout << "喵喵喵...." << endl; // } }; int main(int argc, char const *argv[]) { // Animals a; // 抽象类不能实例化 dog d; d.say(); cat c; // 如果在派生类中没有重写纯虚函数,那么派生类也是抽象类 无法实例化 c.say(); return 0; } |
注意: 如果在派生类中没有重写纯虚函数,那么派生类也是抽象类 无法实例化
总结抽象类的作用:
在项目初期给代码预留出一些框架功能接口, 让派生类去实现
分析项目功能时, 整理需求, 定义出很多功能接口,但是不是马上就去实现,而是先抽象出来,方便后期去实现,防止后面忘记了
C++ class network { public: • //初始化网络功能 virtual void init_network() = 0; • // TCP通信功能 virtual void tcp() = 0 • //UDP通信功能 virtual void udp() = 0 • // 网络数据的校验功能 • ........ }; |
四.C++中的友元
回顾c++类的访问权限:
C++ class base{ public: // 公有成员: 类内 子类 类外 int a; protected: // 保护成员: 类内 子类(子类对象不能直接访问protected 但子类的函数中可以直接访问) int b; private: //私有成员: 类内 int c; } |
1.友元:
作用: 用来访问类中所有的数据成员
缺点: 破坏了类的封装性, 一般不到万不得已, 不要随便使用友元
2.友元函数
语法:
C++ friend 函数返回值类型 函数名(参数){ 函数体 } |
举例:
C++ friend void func(){ //改函数可以访问声明他的类中的所有成员 } |
3.总结友元函数的特点:
- 当一个类中声明了一个友元函数, 那么这个函数就不再属于该类的成员函数
- 友元函数可以在类内任意位置声明, 与成员的权限无关
C++ #include <iostream> using namespace std; class base { public: int a; protected: int b; private: int c; friend void func(); }; // void base::func(){// 加了friend 变成友元后 func不再是base类的成员函数 //base 类的友元函数 void func(){ base a; a.a = 10; a.b = 20; a.c = 30; cout << a.a << "-" << a.b << "-" << a.c << endl; } int main(int argc, char const *argv[]) { func(); return 0; } |

4.友元函数不可以继承
C++ #include <iostream> using namespace std; class base { private: int a; //声明一个友元函数 friend void set(); }; class new_base : base { private: int b; //不能继承 但是可以自己再次声明友元函数 friend void set(); }; void set(){ base m; m.a = 10086; cout << m.a << endl; new_base n; n.b = 10010; // 友元函数不能被继承 // 爸爸的朋友 不能继承给儿子 // 爸爸的朋友没有权限访问儿子的私有 cout << n.b << endl; } int main(int argc, char const *argv[]) { set(); return 0; } |
总结:
1 友元函数不能被继承
2 假如派生类需要友元函数可以访问其私有成员, 可以在派生类中再次声明该函数为友元函数
3 多个类可以对应一个友元函数
4 一个类可以对应多个友元函数
5.友元类
作用: 当一个类做为另外一个类的友元类时, 该类可以访问对方类的一切数据成员
友元类是单向

定义语法:
friend class 类名
举例:
friend class base;
6.互为友元类
- 注意: 一定要在要实例化的类 定义之后,再定义函数接口, 否则无法实例化对象
C++ #include <iostream> using namespace std; class base { public: int a; void show(){ cout << a << " " << b << " " << c << endl; } void set_new_base(); //类内声明 类外定义 protected: int b; private: int c; // 声明new_base是当前base的友元类 friend class new_base; }; //在new_base 中对base里的数据成员进行初始化 class new_base { public: int k; void show(){ cout << k << endl; cout << m << endl; cout << n << endl; } void set_base(); //类内声明 类外定义 protected: int m; private: int n; friend class base; }; // 注意: 一定要在要实例化的类 定义之后,再定义函数接口 // 否则 无法实例化对象 // 注意: 类外定义类内函数,不要忘了 域操作符 void base::set_new_base(){ new_base b; b.k = 123; b.m = 456; b.n = 789; b.show(); } void new_base::set_base(){ base a; a.a = 100; a.b = 200; //无法直接访问类内 保护和私有成员 可以通过友元类实现 a.c = 300; a.show(); //通过a调用show函数 } int main(int argc, char const *argv[]) { new_base b; b.set_base(); base c; c.set_new_base(); return 0; } |
目录
一.多态: 什么是多态???
二.虚析构
三.纯虚函数 与 抽象类
四.C++中的友元