1.继承 ,继承的好处在于减少重复的代码
1.1继承的基本语法 : class 子类 : 继承方式 父类
#include <iostream>
using namespace std;
//建立一个基础类,里面含有顶部、底部以及左部
class Base
{
public:
void header()
{
cout << "首页、公开课、登录、注册...(公共顶部)" << endl;
}
void footer()
{
cout << "帮助中心、站内地图、交流合作...(公共底部)" << endl;
}
void lefter()
{
cout << "Java公开课、Python公开课、C++公开课...(公开课系列)" << endl;
}
};
//建立Java类
class Java : public Base
{
public:
void java()
{
cout << "Java公开课学习" << endl;
}
};
class Python : public Base
{
public:
void python()
{
cout << "Python公开课的学习" << endl;
}
};
void test()
{
Java J1;
J1.footer();
J1.header();
J1.lefter();
J1.java();
cout << "------------------------" << endl;
Python P1;
P1.footer();
P1.header();
P1.lefter();
P1.python();
}
int main() {
test();
system("pause");
return 0;
}
1.2继承的三种方式 : 公共继承、保护继承、私有继承
1.3继承中的对象模型
父类中所有的非静态成员属性都会被子类继承
父类中的私有属性是被编译器隐蔽了,因此是访问不到,但确实是被继承了
可以利用VS中的开发者命令行提示工具查看子类从父类中继承了什么东西
开发者命令行提示工具的使用方法:详看第129节
#include <iostream>
using namespace std;
class Base
{
public:
int m_a;
int m_b;
int m_c;
};
class Son : public Base
{
public:
int m_d;
};
void test()
{
cout << "size of Son = " << sizeof(Son) << endl;
//父类中所有的非静态成员属性都会被子类继承
//父类中的私有属性是被编译器隐蔽了,因此是访问不到,但确实是被继承了,因此Son的大小应该是4个整型的大小 16
}
int main() {
test();
system("pause");
return 0;
}
1.4继承中构造与析构的顺序
在继承中先调用父类的构造函数,再调用子类的构造函数,析构的顺序与构造相反。
1.5继承中同名成员处理方式
访问子类中的同名成员,直接访问即可;
访问父类中的同名成员,需要添加作用域
同理当子类与父类拥有同名的成员函数时,子类会隐藏父类中成员函数,加上作用域之后才可以访问父类中同名的成员函数。
#include <iostream>
using namespace std;
//创建一个父类
class Base
{
public:
Base()
{
m_a = 100;
}
int m_a;
};
//创建子类
class Son : public Base
{
public:
Son()
{
m_a = 200;
}
int m_a;
};
void test01()
{
Son s1;
cout << "Son中的m_a = " << s1.m_a << endl; //直接访问得到的是子类中同名成员
cout << "Base中的m_a = " << s1.Base::m_a << endl;
//通过子类的对象访问父类的成员,需要加上父类的作用域
}
int main() {
test01();
system("pause");
return 0;
}
1.6继承中静态同名成员的处理方式
#include <iostream>
using namespace std;
class Base
{
public:
static int m_a; //创建静态变量需要类内声明,类外初始化
};
int Base::m_a = 10;
class Son : public Base
{
public:
static int m_a;
};
int Son::m_a = 20;
void test01()
{
Son s1;
cout << "Son中的m_a = " << s1.m_a << endl;
cout << "Base中的m_a = " << s1.Base::m_a << endl; //同过子类对象访问父类同名成员需要添加父类的作用域
}
void test02()
{
//由于是静态变量所以具有共享性,可以通过类名的方式访问类内成员
cout << "Son中的m_a = " << Son::m_a << endl;
cout << "Base中的m_a = " << Base::m_a << endl; //通过父类的类名访问父类中成员
cout << "Base中的m_a = " << Son::Base::m_a << endl; //通过子类类名访问父类作用域下的同名成员
}
int main() {
test01();
test02();
system("pause");
return 0;
}
1.7多继承语法
语法:class 子类名 : 继承方式 父类名1,继承方式 父类名2
多继承可能会引起父类中有同名成员的出现,主要加作用域区分。
C++实际开发中不建议使用多继承。
#include <iostream>
using namespace std;
//创建父类1
class Base01
{
public:
Base01()
{
m_A = 10;
}
int m_A;
};
//创建父类2
class Base02
{
public:
Base02()
{
m_B = 20;
}
int m_B;
};
//创建子类
class Son : public Base01, public Base02
{
public:
Son()
{
m_C = 30;
m_D = 40;
}
int m_C;
int m_D;
};
void test01()
{
Son s1;
cout << "Size of Son = " << sizeof(Son) << endl;
cout << "Son中的m_C = " << s1.m_C << endl;
cout << "Base01中的m_A = " << s1.Base01::m_A << endl;
cout << "Base01中的m_A = " << s1.m_A << endl;
}
int main() {
test01();
system("pause");
return 0;
}
2.多态
2.1多态的基本概念
多态分为两类
①静态多态:函数重载与运算符重载属于静态多态,复用函数名
②动态多态:派生类和虚函数实现运行多态
动态多态的满足条件
①需要有继承关系
②子类需要重写父类的虚函数(重写及函数的返回值类型、参数、函数名等全部相同)
动态多态的使用
父类的指针或者引用执行子类对象
静态多态与动态多态的区别:
静态多态的函数地址早绑定,编译阶段确定函数地址
动态多态的函数地址晚绑定,运行阶段确定函数地址
#include <iostream>
using namespace std;
class Animal
{
public:
//Speak就是虚函数
//在前面加上virtual关键字,函数变成虚函数,那么函数在编译阶段就不能确定函数的调用。
virtual void Speak()
{
cout << "动物在说话" << endl;
}
};
class Cat : public Animal
{
public:
void Speak()
{
cout << "小猫在说话" << endl;
}
};
//执行说话函数
//地址早绑定,在编译阶段确定了函数地址
//如果想执行猫说话,那么这个函数地址就不能提前绑定,需要在运行阶段确定即地址晚绑定
//动态多态的满足条件
//1.需要有继承关系
//2.子类需要重写父类的虚函数(重写及函数的返回值类型、参数、函数名等全部相同)
//动态多态的使用
//1.父类的指针或者引用执行子类对象
void DoSpeak(Animal& animal)
{
animal.Speak();
}
void test01()
{
Cat cat;
DoSpeak(cat);
}
int main() {
test01();
system("pause");
return 0;
}
2.2纯虚函数和抽象类
在多态中,通常父类的虚函数是毫无意义的,都是重写子类的虚函数,因此可以将虚函数改为纯虚函数。
纯虚函数语法 : virtual 返回值类型 父类名(参数列表) = 0;
当一个类中有了纯虚函数,那么这个类被称为抽象类。
抽象类的特点:
①无法实例化对象
②抽象类的子类必须要重写父类的纯虚函数,否则也是抽象类,同样也无法实例化对象。
2.3电脑配置小练习(利用多态)
#include <iostream>
using namespace std;
//抽象CPU类
class CPU
{
public:
//抽象的计算函数
virtual void calculate() = 0;
};
//抽象显卡类
class VideoCard
{
public:
//抽象显示函数
virtual void display() = 0;
};
//抽象内存条
class Memory
{
public:
virtual void storage() = 0;
};
//创建一个电脑类
class computer
{
public:
computer(CPU * cpu,VideoCard * vc,Memory *mem)
{
m_cpu = cpu;
m_vc = vc;
m_mem = mem;
}
void work()
{
m_cpu->calculate();
m_vc->display();
m_mem->storage();
}
private:
CPU* m_cpu;
VideoCard* m_vc;
Memory* m_mem;
};
//具体厂商
//Intel
class IntelCPU : public CPU
{
public:
//抽象的计算函数
virtual void calculate()
{
cout << "Intel的CPU开始计算" << endl;
}
};
class IntelVideo : public VideoCard
{
public:
virtual void display()
{
cout << "Intel的显卡开始工作" << endl;
}
};
class IntelMemory : public Memory
{
public:
virtual void storage()
{
cout << "Intel的内存条开始工作" << endl;
}
};
//建立lenovo
class lenovoCPU : public CPU
{
public:
//抽象的计算函数
virtual void calculate()
{
cout << "lenovo的CPU开始计算" << endl;
}
};
class lenovoVideo : public VideoCard
{
public:
virtual void display()
{
cout << "lenovo的显卡开始工作" << endl;
}
};
class lenovoMemory : public Memory
{
public:
virtual void storage()
{
cout << "lenovo的内存条开始工作" << endl;
}
};
void test01()
{
cout << "第一台电脑开始工作" << endl;
Computer *computer01 = new Computer(new IntelCPU, new IntelVideoCard, new IntelMemory);
computer01->work();
cout << "-----------------------------------" << endl;
CPU* lenovocpu = new lenovoCPU;
VideoCard* lenovovc = new lenovoVideo;
Memory* lenovostorage = new lenovoMemory;
computer *computer02 = new computer(lenovocpu, lenovovc, lenovostorage);
computer02->work();
}
int main() {
test01();
system("pause");
return 0;
}
3.文件操作
3.1文本文件(文件已文本的ASCII码形式存储在计算机中)
操作文件的三大类:①ofstream 写文件 ② ifstream 读文件 ③ fstream 读写文件
3.1.2写文件的步骤如下:
①包含头文件 #include <fstream>
②创建流对象 ofstream ofs;
③打开文件 ofs.open("文件路径",打开方式);
④写数据 ofs << "写入的数据" ;
⑤关闭文件 ofs.close();
文件的打开方式分类
ios::in | 为读文件而打开文件 |
ios::out | 为写文件而打开文件 |
ios::ate | 初始位置:文件尾 |
ios::app | 追加方式写文件 |
ios::trunc | 如果文件存在先删除,再创建 |
ios::binary | 二进制方式 |
#include <iostream>
using namespace std;
#include <fstream>
void test01()
{
//创建文件流
ofstream ofs;
//打开文件
ofs.open("test.txt", ios::out); //如果不指定路径那么创造的文件就在当前文件目录之下
//写入数据
ofs << "姓名:张三" << endl;
ofs << "年龄:18" << endl;
ofs << "性别:男" << endl;
//关闭文件
ofs.close();
}
int main() {
test01();
system("pause");
return 0;
}
3.1.3读文件步骤如下:
①包含头文件 #include <istream>
②创建流对象 istream ifs;
③打开文件并判断文件是否成功打开 ifs.open("文件路径",打开方式);
④读数据:四种读取方式
⑤关闭文件 ifs.close();
#include <iostream>
using namespace std;
#include <fstream>
void test01()
{
//创建文件流
ifstream ifs;
//打开文件并判断文件是否打开成功
ifs.open("D:/c++项目/学习/test.txt", ios::in);
if (!ifs.is_open())
{
cout << "文件打开失败" << endl;
return;
}
//读文件
char buf[1024] = { 0 };
while (ifs >> buf)
{
cout << buf << endl;
}
//关闭文件
ifs.close();
}
int main() {
test01();
system("pause");
return 0;
}