继承与多态

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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值