● 继承是面向对象的三大特性之一
● 好处:减少重复代码
● 语法:class 子类 : 继承方式 父类
● 子类:派生类
● 父类:基类
继承方式
● 语法:class 子类 : 继承方式 父类
● 继承方式:
○ 公共继承
■ public 和 protected 权限不变
■ 父类中私有成员不能访问
○ 保护继承
■ public 和 protected 都成为 protected 成员
■ 父类中私有成员不能访问
○ 私有继承
■ 父类中的所有成员都变成 private
■ 父类中私有成员不能访问
● 父类中所有非静态成员属性都会被子类继承
● 父类中的私有成员只是被编译器隐藏,不能访问,但是实际被继承了
● 继承中的构造:先构造父类,再构造子类;
● 继承中的析构:先析构子类,再析构父类;
● 问题:当子类与父类出现同名的成员,如何通过子类对象,访问到子类或者父类中同名的数据呢?
○ 访问子类同名成员:直接访问即可;
○ 访问父类同名成员:需要加作用域;
■ 如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类所有同名的成员函数;
■ 如果想访问,必须加作用域;
● 问题:继承中同名的静态成员在子类对象上如何进行访问?
○ 静态成员和非静态成员出现同名,处理方式一致;
○ 访问子类:直接访问;
○ 访问父类:加作用域;
多继承语法
● C++允许一个类多继承;
○ 语法:class 子类 : 继承方式 父类, 继承方式 父类, ……;
○ 多继承可能会引发父类中有同名成员出现,需要加作用域区分;
○ C++实际开发中不建议使用多继承;
菱形继承
● 菱形继承概念:
○ 两个派生类继承同一个基类;
○ 又是某个类同时继承两个派生类;
○ 这种继承成为菱形继承或者钻石继承;
● 关键字:virtual
○ 在继承的时候加上关键字后变成虚继承;
○ 虚继承中相同的数据是共享的;
多态的基本概念
● 多态是面向对象的三大特征之一
○ 多态的分为两类
■ 静态多态:函数重载和运算符重载属于静态多态,服用函数名;
■ 动态多态:派生类和虚函数实现运行时多态;
○ 静态多态和动态多态的区别
■ 静态多态的函数地址早绑定 - 编译阶段确定函数地址;
■ 动态多态的函数地址晚绑定 - 运行阶段确定函数地址;
● 有继承关系;
● 子类重写父类的虚函数;
○ 虚函数:函数前用virtual关键字说明;
○ 重写:函数返回值类型相同、函数名相同、函数参数列表完全相同;
多态的优点
● 代码组织结构清晰;
● 可读性强;
● 利于前期和后期的扩展以及维护;
○ 开闭原则:对扩展进行开放,对修改进行关闭;
纯虚函数和抽象类
纯虚函数
● 语法:virtual 返回值类型 函数名 (参数列表) = 0;
● 当类中有了纯虚函数,这个类成为抽象类;
● 抽象类特点:
○ 无法实例化对象;
○ 子类必须重写抽象类中的纯虚函数,否则也属于抽象类;
虚析构和纯虚析构
● 问题:多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码;
○ 父类指针指向父类的对象,则在父类析构的时候,不会调用子类中的析构函数,导致子类如果有堆区属性,出现泄漏。
● 解决方式:将父类中的析构函数改为虚析构或者纯虚析构;
○ 纯虚析构:既要声明也要实现,及需要在内外将其实现,不然不能通过编译;
● 虚析构和纯虚析构的共性
○ 可以解决父类指针释放子类对象;
○ 都需要具体的函数实现;
● 虚析构和纯虚析构的区别
○ 如果是纯虚析构,该类属于抽象类,无法实例化;
● 虚析构语法:virtual ~类名(){}
● 纯虚析构语法:virtual ~类名() = 0;
● 程序运行时产生的数据都属于零时数据,程序一旦运行结束都会被释放;
● 通过文件可以将数据持久化;
● C++中对文件 *** 作需要包含头文件
● 文件类型分为两种:
○ 文本文件:文件以文本的ASCII码形式存储在计算机中,用户一般不能直接读懂它们;
● *** 作文件的三大类:
○ ofstream:写 *** 作
○ ifstream:读 *** 作
○ fstream:读写 *** 作
写文件
● 步骤
○ 包含头文件:#include
○ 创建流对象:ofstream ofs;
○ 打开文件:ofs.open("文件路径",打开方式);
○ 写数据:ofs << "写入的数据";
○ 关闭文件:ofs.close();
● 文件打开方式
○ 注意:文件打开方式可以配合,利用 | *** 作符;
○ 例如:用二进制方式写文件ios::binary | ios::out
// // Created by NJUST'er'wang's on 2022/1/18. //文本文件 写文件 #include#include using namespace std; void test01(){ ofstream ofs; ofs.open("test.txt",ios::out); ofs << "姓名:王东" < 读文件 ● 读文件与写文件步骤相似,但是读取方式相对于比较多;
● 步骤
○ 包含头文件:#include
○ 创建流对象:ifstream ifs;
○ 打开文件并判断文件是否打开成功:ifs.open("文件路径",打开方式);
○ 读数据:四种读方式;
○ 关闭文件:ifs.close();// // Created by NJUST'er'wang's on 2022/1/18. //文本文件 读文件 #include#include #include using namespace std; void test01(){ ifstream ifs; ifs.open("test.txt",ios::in); if(!ifs.is_open()) { cout<<"打开文件失败!"< ● 读数据
//first method char buf[1024] = {0}; while (ifs >> buf) { cout< //second method char buf2[1024] = {0}; while(ifs.getline(buf2,sizeof(buf2))) { cout< //third method string str; while (getline(ifs,str)) { cout< //forth method char ch; while ((ch = ifs.get()) != EOF ) //EOF end of file { cout< ifs.close(); } int main() { test01(); return 0; }二进制文件● 以二进制的方式对文件进行读写 *** 作;
● 打开方式指定为:ios::binary
写文件
● 二进制文件主要利用流对象调用成员函数write
● 函数原型:ostream& write(const char * buffer,int len);
● 参数解释:字符指针buffer指向内存中一段存储空间。len是读写的字节数;// // Created by NJUST'er'wang's on 2022/1/18. //二进制文件 写文件 #include读文件#include #include using namespace std; class Person { char name[10]; int age; public: Person(char name[10], int age) { strcpy(this->name, name); this->age = age; } char *getName() { return name; } int getAge() { return age; } }; void test01() { ofstream ofs; ofs.open("Person.txt", ios::out | ios::binary); Person p = {"唐潇", 24}; ofs.write((const char *) &p, sizeof(Person)); ofs.close(); } int main() { test01(); return 0; } ● 二进制方式读文件主要利用流对象调用成员函数read;
● 函数原型:istream& read(char *buffer,int len);
● 参数解释:字符指针buffer指向内存中一段存储空间。len是读写的字节数;// // Created by NJUST'er'wang's on 2022/1/18. //二进制文件的读文件 #include#include #include using namespace std; class Person { char name[10]; int age; public: Person() {} Person(char name[10], int age) { strcpy(this->name, name); this->age = age; } char *getName() { return name; } int getAge() { return age; } }; void test01() { ifstream ifs; ifs.open("Person.txt", ios::in | ios::binary); if (!ifs.is_open()) { cout << "打开文件失败!" << endl; return; } Person p; ifs.read((char *) &p, sizeof(Person)); cout << "name: " << p.getName() << ' ' << "age: " << p.getAge() << endl; ifs.close(); } int main() { test01(); return 0; } 欢迎分享,转载请注明来源:内存溢出
评论列表(0条)