B站黑马c++学习笔记 —— 核心编程篇

大纲

1 内存分区模型

在这里插入图片描述

1.1 程序运行前

在这里插入图片描述
在这里插入图片描述

1.2 程序运行后

在这里插入图片描述
在这里插入图片描述

//在堆区开辟数据
int * func(){
	int * a = new int(100); //利用new关键字,可以将数据开辟到堆区
	return a;
}

int main(){
	...
	int * p = func();
	cout << *p << endl;
	cout << *p << endl;
	delete p; //释放堆区数据
	...
}

1.3 new操作符

在这里插入图片描述

//在堆区开辟数组
void func() {
	int * arr = new int[10]; //10为数组元素个数
	for (int i = 0; i < 10; i++) {
		arr[i] = i + 100;
	}
	for (int i = 0; i < 10; i++) {
		cout << arr[i] << endl;
	}
	delete[] arr;//释放堆区数组
}

int main(){
	...
	func();
	...
}

2 引用

2.1 引用的基本使用

在这里插入图片描述

2.2 引用注意事项

在这里插入图片描述

2.3 引用的做函数参数

在这里插入图片描述

void swap(int &a,int &b) {
	int temp = a;
	a = b;
	b = temp;
}

int main() {
...
	int a = 1;
	int b = 2;
	swap(a, b);
	cout << a << endl;
	cout << b << endl;
...
}

2.4 引用做函数返回值

在这里插入图片描述

//局部变量引用不能返回,在函数调用完后,局部变量会被清除
int& ret() {
	static int a = 10; //静态变量,放在全局区,在程序结束后才清除
	return a;
}

int main() {
	...
	int &ref = ret();
	cout << "ref_1=" << ref << endl;
	cout << "ref_1=" << ref << endl;
	ret() = 100; //函数调用可以作为左值
	cout << "ref_2=" << ref << endl;
	cout << "ref_2=" << ref << endl;
	...
}

在这里插入图片描述

2.5 引用的本质

在这里插入图片描述

//引用的本质:指针常量
int& ref = a;
int * const ref = &a;

2.6 常量引用

在这里插入图片描述

const int& ref = 10;
//防止形参修改实参
void show(const int& a) {
	cout << a << endl;
}

int main() {
	...
	int a = 1;
	show(a);
	...
}

3 函数提高

3.1 函数默认参数

在这里插入图片描述

  1. 如果传入数据就用传入的数据(b=20),如果没有,就用默认值(b=10);
  2. 默认参数必须在最后,不能在中间;
  3. 函数的声明和实现只能有一个设置默认参数,不能同时;
int func(int a,int b = 10){
	...
}

int main{
	...
	func(10,20)
	...
}

3.2 函数占位参数

在这里插入图片描述

void func(int a,int ){
	...
}

int main{
	...
	func(10,20)
	...
}

3.3 函数重载

3.3.1 函数重载概述

3.3.2 函数重载注意事项

在这里插入图片描述

  1. 引用的函数重载
void func(int a, int b){
	...
}
void func(int a, int b){ 
	...
}

int main(){
	...
	int a=10;
	func(a);

	func(10)
	...
}
  1. 默认参数的函数重载,应该尽量避免

4 类和对象

在这里插入图片描述

4.1 封装

4.1.1 封装的意义一

在这里插入图片描述

const double PI = 3.14;

//圆类
class circle 
{
//访问权限
public:
	//半径
	double m_r;
	//获取周长
	double m_perimeter() { 
		return 2 * PI * m_r;
	}
};

int main() {
	//创建对象 实例化
	circle c1;
	c1.m_r = 2.1;
	cout << "圆的周长为:" << c1.m_perimeter() << endl;
	...
}

在这里插入图片描述

//类中的属性与行为--成员
//属性--成员属性、成员变量
//行为--成员函数、成员方法
const int MAX = 1000;
int num = 0;//输入学生计数

class student
{
//访问权限
public:
	string arr_name[MAX];
	int arr_id[MAX];
	//信息输入
	void input() {
			cout << "姓名:" << endl;
			cin >> arr_name[num];
			cout << "学号:" << endl;
			cin >> arr_id[num];
			num++;
	}
	//信息打印
	void output() {
		for (int i = 0; i < num; i++) {
			cout << "姓名:" << arr_name[i] << endl;
			cout << "学号:" << arr_id[i] << endl;
		}
	}
};

int main() {
	student arr_stu;//对象
	int stu_num = 3;//输入学生数
	for (int i = 0; i < stu_num; i++) {
		arr_stu.input();
	}
	arr_stu.output();
	...
}

4.1.2 封装的意义二

在这里插入图片描述

公共权限 成员 类内可以访问 类外可以访问
保护权限 成员 类内可以访问 类外不可以访问 子类可以访问父类的保护内容
私有权限 成员 类内可以访问 类外不可以访问 子类不可以访问父类的私有内容

class student
{
//公共权限
public:
	...
//保护权限
protected:
	...
//私有权限
private:
	...
};

4.1.3 struct与class区别

在这里插入图片描述

4.1.3 成员属性设置为私有

在这里插入图片描述

4.1.4 案例一 立方体判断

在这里插入图片描述

class cube {
public:
	//设置属性
	void set_lwh(int l,int w,int h) {
		m_l = l;
		m_w = w;
		m_h = h;
	}
	//获取属性
	int get_l() {
		return m_l;
	}
	int get_w() {
		return m_w;
	}
	int get_h() {
		return m_h;
	}
	//获取结果
	int cal_S() {
		return 2 * m_l * m_w + 2 * m_l * m_h + 2 * m_h * m_w;
	}
	int cal_V() {
		return m_l * m_w * m_h;
	}
	//成员判断
	//只用传入一个对比的值,有一个是已知的
	bool isSame1(cube &c) {
		if (m_l == c.get_l() && m_h == c.get_h() && m_w == c.get_w()) {
			return true;
		}
		return false;
	}
protected:
private:
	int m_l;
	int m_w;
	int m_h;
};
//全局判断
bool isSame2(cube &c1, cube &c2) {
	if (c1.get_l() == c2.get_l() && c1.get_h() == c2.get_h() && c1.get_w() == c2.get_w()) {
		return true;
	}
	return false;
}

int main() {
	cube c1;
	cube c2;
	cube c3;
	//设置长 宽 高
	c1.set_lwh(1, 2, 3);
	c2.set_lwh(1, 2, 3);
	c3.set_lwh(2, 2, 3);
	cout << c1.cal_S() << endl;
	cout << c1.cal_V() << endl;
	//成员对比
	bool ret1 = c1.isSame1(c2);
	bool ret3 = c1.isSame1(c3);
	//全局对比
	bool ret2 = isSame2(c1,c2);
	bool ret4 = isSame2(c1,c3);
	if (ret1 && ret2) {
		cout << "1,2 一样" << endl;
	}
	else {
		cout << "1,2 不一样" << endl;
	}
	if (ret3 && ret4) {
		cout << "1,3 一样" << endl;
	}
	else {
		cout << "1,3 不一样" << endl;
	}
	...
}

4.1.5 案例二 点圆关系判断 及 class 的头文件封装

在这里插入图片描述

//点类
class point {
public:
	void set_xy(int x, int y) {
		p_x = x;
		p_y = y;
	}
	int get_x() {
		return p_x;
	}
	int get_y() {
		return p_y;
	}
private:
	//位置xy
	int p_x;
	int p_y;
protected:
};
//圆类
class circle {
public:
	void set_r(int r) {
		c_r = r;
	}
	void set_o(point c) {
		c_o = c;
	}
	int get_r() {
		return c_r;
	}
	point get_o() {
		return c_o;
	}
private:
	//圆心xy
	point c_o;
	//半径
	int c_r;
protected:
};
//距离比较
void c_p(circle &c, point &p) {
	int distence_cp = (c.get_o().get_x() - p.get_x()) * (c.get_o().get_x() - p.get_x()) + (c.get_o().get_y() - p.get_y()) * (c.get_o().get_x() - p.get_x()) - c.get_r() * c.get_r();
	if (distence_cp == 0) {
		cout << "点在圆上" << endl;
	}
	else if (distence_cp > 0) {
		cout << "点在圆外" << endl;
	}
	else {
		cout << "点在圆内" << endl;
	}
}

int main() {
	//定义点和圆对象
	circle c;
	point c_o;
	point p1;
	point p2;
	point p3;
	//设置圆属性
	c.set_r(2);
	c_o.set_xy(0, 0);
	c.set_o(c_o);
	//设置点属性及比较
	p1.set_xy(2, 0);
	c_p(c, p1);
	p2.set_xy(1, 0);
	c_p(c, p2);
	p3.set_xy(3, 0);
	c_p(c, p3);
	...
}

把类封装成.h文件

  1. point.h
#pragma once
#include<iostream>
using namespace std;

class point {
public:
	void set_xy(int x, int y);
	int get_x();
	int get_y();
private:
	//位置xy
	int p_x;
	int p_y;
protected:
};
  1. circle.h
#include"point.h"

class circle {
public:
	void set_r(int r);
	void set_o(point c);
	int get_r();
	point get_o();
private:
	//圆心xy
	point c_o;
	//半径
	int c_r;
protected:
};
  1. point.cpp
#include"point.h"

void point::set_xy(int x, int y) {
	p_x = x;
	p_y = y;
}
int point::get_x() {
	return p_x;
}
int point::get_y() {
	return p_y;
}
  1. circle.cpp
#include"circle.h"

void circle::set_r(int r) {
	c_r = r;
}
void circle::set_o(point c) {
	c_o = c;
}
int circle::get_r() {
	return c_r;
}
point circle::get_o() {
	return c_o;
}
  1. 主函数.cpp
#include"circle.h"

void c_p(circle &c, point &p) {
	int distence_cp = (c.get_o().get_x() - p.get_x()) * (c.get_o().get_x() - p.get_x()) + (c.get_o().get_y() - p.get_y()) * (c.get_o().get_x() - p.get_x()) - c.get_r() * c.get_r();
	if (distence_cp == 0) {
		cout << "点在圆上" << endl;
	}
	else if (distence_cp > 0) {
		cout << "点在圆外" << endl;
	}
	else {
		cout << "点在圆内" << endl;
	}
}

int main() {
	circle c;
	point c_o;
	point p1;
	point p2;
	point p3;
	c.set_r(2);
	c_o.set_xy(0, 0);
	c.set_o(c_o);
	p1.set_xy(2, 0);
	c_p(c, p1);
	p2.set_xy(1, 0);
	c_p(c, p2);
	p3.set_xy(3, 0);
	c_p(c, p3);
	...
}

4.2 对象的初始化与清理

4.2.1 构造函数和析构函数

在这里插入图片描述
在这里插入图片描述

class test{
public:
	test(...){
		cout << "test的构造函数" << endl ;
	}
	...
	~test(){
	cout << "test的析构函数" << endl ;
	}
	...
};

4.2.2 构造函数的分类及调用

在这里插入图片描述

class test{
public:
	test(){
		cout << "test的无参构造函数" << endl ;
	}
	...
	test(int a){
		cout << "test的有参构造函数" << endl ;
	}
	...
	test(const test &t){
		cout << "test的拷贝构造函数" << endl ;
	}
	...
};
//构造函数的调用
void usage(){
	//括号法
	test t1;	//默认构造函数的调用不加()
	test t2(10);
	test t3(t2);
	//显示法
	test t1;	
	test t2 = test(10);	//test(10)为匿名对象,当前执行后,系统自动回收
	test t3 = test(t2);	//不要利用拷贝构造函数初始化匿名对象 test(t2) == test t2; 重定义
	//隐式转换法
	test t4 = 10;	//等价于 test t4 = test(10)
	test t5 = t4;	//等价于 test t5 = test(t4)
}

4.2.3 拷贝构造函数调用时机

在这里插入图片描述

4.2.4 构造函数调用规则

在这里插入图片描述

4.2.5 深拷贝与浅拷贝

在这里插入图片描述

class person {
public:

	int m_age;
	int* m_high;
	person() {
		cout << "person的无参构造函数" << endl;
	}

	person(int age,int high) {
		m_age = age;
		m_high = new int(high);
		cout << "person的有参构造函数" << endl;
	}

	person(const person &p) {
		m_age = p.m_age;
		//m_high = p.m_high;
		m_high = new int(*p.m_high); //深拷贝,重新在堆区开辟空间存储
		cout << "person的拷贝构造函数" << endl;
	}

	~person() {
		//析构函数释放堆区数据 浅拷贝会重复释放 报错
		if (m_high != NULL) {
			delete m_high;
			m_high = NULL;
		}
		cout << "tperson的析构构函数" << endl;
	}
};

void test() {
	person p1(18,170);
	person p2(p1);
	cout << p1.m_age << *p1.m_high << endl;
	cout << p2.m_age << *p2.m_high << endl;
}

int main() {
	
	test();
	...
}

在这里插入图片描述
在这里插入图片描述

4.2.6 初始化列表

在这里插入图片描述

class person{
public:
	int m_a;
	int m_b;
	person(int a, int b) : m_a(a), m_b(b){
		...
	}
	...
};
void test(){
	person p(1,2);
}

4.2.7 类对象作为类成员

在这里插入图片描述

  • A先构造,B后构造
  • B先析构,A后析构

4.2.8 静态成员

在这里插入图片描述

class person {
public:
	int m_b;//非静态成员变量
	static int m_a;//静态成员变量
	static void func() {//静态成员函数有访问权限public、private、protect的区分
		m_a = 100;
		//m_b = 100;//不可以访问非静态成员变量,无法区分是哪个对象的属性 
		cout << "static void func调用" << endl;
	}
};

int person::m_a = 0;//初始化

void test() {
	// 1、通过对象访问
	person p1;
	p1.func();
	
	// 2、通过类名访问,不属于某个对象
	person::func();
}

int main() {
	test();
	...
}

4.3 C++对象模型和this指针

4.3.1 成员变量和成员函数分开存储

在这里插入图片描述 - 空类和空对象所占的内存为 1

4.3.2 this指针概念

在这里插入图片描述

class person {
public:
	int age;
	person(int age) {
		//age = age;
		this->age = age;
	}

	//返回类型的应该是 person& 引用,而不是 person ,不然不是本体
	person& add(person &p) {
		this->age += p.age;
		// this 是指向 p2 的指针,则 *this 指向的是 p2 的本体
		return *this;
	}
};

void test() {
	person p1(18);
	cout << p1.age << endl;
	person p2(10);
	p2.add(p1).add(p1); //p2.add()的返回值为 p2 本体,可一直调用
	cout << p2.age << endl;
}

int main() {
	test();
	...
}

4.3.3 空指针访问成员函数

在这里插入图片描述

class person {
public:
	int m_age;
	void show_class(){
		cout << "show_class" << endl;
	}
	void show_age() {
		if (this == NULL) {
			return;
		}
		cout << m_age << endl;
	}
};

void test() {
	person * p = NULL;
	p->show_class();
	p->show_age(); // 空指针无法找到数据 会报错

}

int main() {

	test();
	...
}

4.3.4 const修饰成员函数

在这里插入图片描述

class person {
public:
	int m_age;
	mutable int m_AGE; //在常函数中也可以修改

	// this 指针的本质是 指针常量 ,指针的指向不能修改
	//成员函数的const修饰的是this指针,使其指向的值也不可以修改
	void show_person() const
	{
		//this = NULL; //指针指向不可以修改
		//this->m_age = 100; //指针指向的值也不可以修改
		this->m_AGE = 100;
	}
	
	void func() {}
};

void test() {
	person p1;
	p1.show_person();

	const person p2; //常对象
	//p2.m_age = 10; //不可修改其属性
	p2.m_AGE = 100; //特殊值

	//常对象只能调用常函数
	p1.show_person();
	p2.show_person(); 
	//p2.func();
}

int main() {
	test();
	...
}

4.4 友元

在这里插入图片描述

4.4.1 全局函数做友元

class building {
	//全局函数是building的友元
	friend void goodgay(building &build);
public:
	building() {
		m_sit = "客厅";
		m_bed = "卧室";
	}
	string m_sit;
private:
	string m_bed;
};
//全局函数
void goodgay(building &build) {
	cout << " 正在访问  " << build.m_sit << endl;
	cout << " 正在访问  " << build.m_bed << endl;
}

void test() {
	building build1;
	goodgay(build1);
}

int main() {
	test();
	...
}

4.4.2 类做友元

class building {
	//类做友元
	friend class goodgay;
public:
	building();
	string m_sit;
private:
	string m_bed;
};

class goodgay {
public:
	goodgay();
	void visit();
	building* build;
};

//类外写成员函数
goodgay::goodgay() {
	//创建建筑对象
	build = new building;
}
void goodgay::visit() {
	cout << " 正在访问  " << build->m_sit << endl;
	cout << " 正在访问  " << build->m_bed << endl;
}
building::building() {
	m_sit = "客厅";
	m_bed = "卧室";
}

void test() {
	goodgay gay1;
	gay1.visit();
}

int main() {
	test();
	...
}

4.4.3 成员函数做友元

class building;
class goodgay {
public:
	goodgay();
	void visit();
private:
	building* build;
};
class building {
	//成员函数做友元
	friend void goodgay::visit();
public:
	building();
	string m_sit;
private:
	string m_bed;
};
//类外写成员函数
goodgay::goodgay() {
	//创建建筑对象
	build = new building;
}
void goodgay::visit() {
	cout << " 正在访问  " << build->m_sit << endl;
	cout << " 正在访问  " << build->m_bed << endl;
}
building::building() {
	m_sit = "客厅";
	m_bed = "卧室";
}
void test() {
	goodgay g1;
	g1.visit();
}

int main() {
	test();
	...
}

4.5 运算符重载

在这里插入图片描述

4.5.1 加号运算符重载

在这里插入图片描述

class num {
public:
	int m_a;
	int m_b;
	num() {};
	num(int a,int b) {
		this->m_a = a;
		this->m_b = b;
	};
	//num operator+(num &num);
};

//成员函数重载
//num num::operator+(num &num1) {
//	num num_temp;
//	num_temp.m_a = this->m_a + num1.m_a;
//	num_temp.m_b = this->m_b + num1.m_b;
//	return num_temp;
//}

//全局函数重载
num operator+(num &num1,num &num2) {
	num num_temp;
	num_temp.m_a = num1.m_a + num2.m_a;
	num_temp.m_b = num1.m_b + num2.m_b;
	return num_temp;
}

void test() {
	num num1(2,4);
	num num2(3,5);
	num num3 = num1 + num2;

	//成员函数调用的本质:num num3 = num1.operator+(num2)
	//cout << "成员函数a: "<<num3.m_a << endl;
	//cout << "成员函数b: "<<num3.m_b << endl;

	//全局函数调用的本质:num num3 = operator+(num1,num2)
	cout << "全局函数a: " << num3.m_a << endl;
	cout << "全局函数b: " << num3.m_b << endl;

	//运算符重载 也可以发生函数重载 即两个operator+的输入参数不同
}

int main() {
	test();
	...
}

4.5.2 左移运算符重载

在这里插入图片描述

class left_move {
	friend ostream& operator<<(ostream &cout, left_move &left_1);
public:
	left_move(int a,int b) {
		this->m_a = a;
		this->m_b = b;
	}
	//p.operator<<(cout)
	//不会利用成员函数重载<<运算符,因为无法实现<<在左侧
private:
	int m_a;
	int m_b;
};
//全局函数重载
ostream& operator<<(ostream &cout, left_move &left_1) {
	cout <<" m_a = "<< left_1.m_a << endl;
	cout <<" m_b = "<< left_1.m_b << endl;
	return cout;
}
void test() {
	left_move left_1(1,2);
	cout << left_1 << endl;
}

int main() {
	test();
	...
}

4.5.3 递增运算符重载

在这里插入图片描述

class my_int {
	friend ostream& operator<<(ostream &cout,my_int my_int);
public:
	my_int() {
		this->m_num = 0;
	}

	//前置递增重载 返回的是引用 为了对一个数进行重复操作
	my_int& operator++() {
		this->m_num++;
		return *this;
	}

	//后置递增重载 返回的是值而不是引用 int用于区分前置和后置
	my_int operator++(int) {
		my_int temp = *this;
		this->m_num++;
		return temp;
	}

private:
	int m_num;
};

//左移重载 对象不加引用,后置返回的temp是不可修改的值
ostream& operator<<(ostream &cout,my_int my_int) {
	cout << my_int.m_num << endl;
	return cout;
}

void test() {
	//前置
	my_int my_int1;
	cout << my_int1 << endl;
	cout << ++my_int1 << endl;
	cout << my_int1 << endl;
	//后置
	my_int my_int2;
	cout << my_int2 << endl;
	cout << my_int2++ << endl;
	cout << my_int2 << endl;
}

int main() {
	test();
	...
}

4.5.4 赋值运算符重载

在这里插入图片描述

class person {
	friend void test();
public:
	person(int age) {
		//在堆区开辟内存存储,并用m_age指针维护
		m_age = new int(age);
	}
	~person() {
		if (m_age != NULL) {
			delete m_age;
			m_age = NULL; 
		}
	}
	//赋值重载
	person& operator=(person &p) {
		//编译器默认:浅拷贝
		//m_age = p.m_age;
		//先释放本身堆区的内存
		if (m_age != NULL) {
			delete m_age;
			m_age = NULL;
		}
		//深拷贝
		this->m_age = new int(*p.m_age);
		return *this;
	}
private:
	int* m_age;
};

void test(){
	person p1(17);
	person p2(24);
	person p3(38);
	p3 = p2 = p1;
	cout << *p1.m_age << "\t" << *p2.m_age << "\t" << *p3.m_age << endl;
}

int main() {
	test();
	...
}

4.5.5 关系运算符重载

在这里插入图片描述

class person {
public:
	person(string name,int age) {
		this->m_name = name;
		this->m_age = age;
	}
	//重载 ==
	bool operator==(person &p) {
		if (this->m_name == p.m_name && this->m_age == p.m_age) {
			return true;
		}
		return false;
	}

private:
	string m_name;
	int m_age;
};

void test() {
	person p1("a", 1);
	person p2("b", 1);
	if (p1 == p2) {
		cout << " 1 , 2相等 " << endl;
	}
	else {
		cout << " 1 , 2不等 " << endl;
	}
}

int main() {
	test();
	...
}

4.5.6 函数调用运算符重载

在这里插入图片描述

class my_add {
public:
	int operator()(int a,int b) {
		return a + b;
	}
private:
};
void test() {
	my_add add1;
	int ret = add1(1,1);
	cout << ret << endl;
	//匿名函数对象:my_add()
	cout << my_add()(2,2) << endl;
}

int main() {
	test();
	...
}

4.6 继承

在这里插入图片描述

4.6.1 继承的基本语法

在这里插入图片描述

//公共页面
class comm {
public:
	void header() {
		cout << "h1,h2,h3,..." << endl;
	}
	void footer() {
		cout << "f1,f2,f3,..." << endl;
	}
};
//继承
class java : public comm {
public:
	void content() {
		cout << "JAVA" << endl;
	}
};

class python : public comm {
public:
	void content() {
		cout << "PYTHON" << endl;
	}
};

void test() {
	//cout << "JAVA界面" << endl;
	python ja;
	ja.header();
	ja.content();
	ja.footer();

	//cout << "PYthon界面" << endl;
	java py;
	py.header();
	py.content();
	py.footer();
}

int main() {
	test();
	...
}

4.6.2 继承方式

在这里插入图片描述
在这里插入图片描述

4.6.3 继承中的对象模型

在这里插入图片描述

class base {
public:
	int m_a;
protected:
	int m_b;
private:
	int m_c;
};

class son : public base {
public:
	int m_d;
};

void test() {
	//父类中所有的非静态成员属性都会被子类继承
	cout << sizeof(son) << endl;
}

int main() {
	test();
	...
}

在这里插入图片描述

4.6.4 继承中构造和析构顺序

在这里插入图片描述

class base {
public:
	base() {
		cout << "base的构造函数" << endl;
	}
	~base() {
		cout << "base的析构函数" << endl;
	}
};

class son : public base {
public:
	son() {
		cout << "son的构造函数" << endl;
	}
	~son() {
		cout << "son的析构函数" << endl;
	}
};

void test() {
	son s1;
}

int main() {
	test();
	...
}
  • 构造:先构造父类,再构造子类
  • 析构:先析构子类,在析构父类

在这里插入图片描述

4.6.5 继承同名成员处理方式

在这里插入图片描述

class base {
public:
	int m_age;
	base() {
		m_age = 70;
	}
	void func() {
		cout << "base -- func" << endl;
	}
};

class son : public base {
public:
	int m_age;
	son() {
		m_age = 40;
	}
	void func() {
		cout << "son -- func" << endl;
	}
};

void test() {
	son s1;
	//同名变量
	cout << s1.m_age << endl;
	cout << s1.base::m_age << endl;
	//同名函数
	s1.func();
	s1.base::func();
}

int main() {
	test();
	...
}

在这里插入图片描述

4.6.6 继承同名静态成员处理方式

在这里插入图片描述

class base {
public:
	//类内声明 类外初始化
	static int m_age;
	static void func() {
		cout << "base -- func" << endl;
	}
};
int base::m_age = 70;

class son : public base {
public:
	static int m_age;
	static void func() {
		cout << "son -- func" << endl;
	}
};
int son::m_age = 30;

void test() {
	//通过对象访问
	son s1;
	cout << s1.m_age << endl;
	cout << s1.base::m_age << endl;
	s1.func();
	s1.base::func();
	//通过类名访问
	cout << son::m_age << endl;
	cout << son::base::m_age << endl;
	son::func();
	son::base::func();
}

int main() {
	test();
	...
}

在这里插入图片描述

4.6.7 多继承语法

在这里插入图片描述

class base1 {
public:
	int m_a;
	base1() {
		m_a = 70;
	}
};

class base2 {
public:
	int m_a;
	base2() {
		m_a = 60;
	}
};

class son : public base1 , public base2 {
public:
	int m_a;
	son() {
		m_a = 30;
	}
};

void test() {
	son s1;
	cout << sizeof(s1) << endl;
	cout << s1.m_a << endl;
	cout << s1.base1::m_a << endl;
	cout << s1.base2::m_a << endl;
}

int main() {
	test();
	...
}

4.6.8 菱形继承

在这里插入图片描述
在这里插入图片描述

class animal {
public:
	int m_age;
	animal() {
		m_age = 18;
	}
};

//利用虚继承(实际继承的为指针--其指向的是偏移table) 解决菱形继承问题
//在继承前加上关键字 virtual
//父类(animal)称为虚基类
class sheep : virtual public animal {};
class tuo 	: virtual public animal {};
class sheep_tuo : public sheep , public tuo {};

void test() {
	sheep_tuo st1;
	cout << st1.m_age << endl;
	cout << st1.sheep::m_age << endl;
	cout << st1.tuo::m_age << endl;

	st1.sheep::m_age = 100;
	cout << st1.sheep::animal::m_age << endl;
	cout << st1.m_age << endl;
	cout << st1.sheep::m_age << endl;
	cout << st1.tuo::m_age << endl;
}

int main() {
	test();
	...
}

4.7 多态

4.7.1 多态的基本概念

在这里插入图片描述

class animal {
public:
	//虚函数 可以让dospeak函数地址 -- 晚绑定
	virtual void speak() {
		cout << "animal - - speak" << endl;
	}
};

class cat : public animal {
public:
	void speak() {
		cout << "cat - - speak" << endl;
	}
};

//函数地址会在编译阶段 -- 早绑定
//父类和子类的类型可以同用 不用转换 animal &animal = cat
void dospeak(animal &animal) {
	animal.speak();
}

void test() {
	cat c1;
	dospeak(c1);
}

int main() {
	test();
	...
}

在这里插入图片描述

4.7.2 多态案例一 计算器类

在这里插入图片描述

  • 普通写法
class cacul {
public:
	int num_a;
	int num_b;
	string oper;

	cacul(int num_a, int num_b, string oper) {
		this->num_a = num_a;
		this->num_b = num_b;
		this->oper = oper;
	};

	int getresult(string oper) {
		if (oper == "+") {
			return num_a + num_b;
		}
		else if (oper == "-") {
			return num_a - num_b;
		}
		else if (oper == "*") {
			return num_a * num_b;
		}
	}
};

void test() {
	cacul c1(4, 2, "*");
	cout << c1.getresult(c1.oper) << endl;

int main() {
	test();
	...
}
  • 多态技术
class abs_cacul {
public:
	int m_num1;	//操作数1
	int m_num2;	//操作数2
	//纯虚函数 在父类中无意义 主要是调用子类重写的内容
	virtual void getresult(int m_num1, int m_num2) = 0;
};
//加法
class add_cacul : public abs_cacul {
public:
	virtual void getresult(int m_num1, int m_num2) {
		cout << m_num1 + m_num2 << endl;
		return ;
	}
};
//减法
class sub_cacul : public abs_cacul {
public:
	virtual void getresult(int m_num1, int m_num2) {
		cout << m_num1 - m_num2 << endl;;
		return ;
	}
};
//乘法
class mul_cacul : public abs_cacul {
public:
	virtual void getresult(int m_num1, int m_num2) {
		cout << m_num1 * m_num2 << endl;
		return ;
	}
};
//除法
class div_cacul : public abs_cacul {
public:
	virtual void getresult(int m_num1, int m_num2) {
		cout << m_num1 / m_num2 << "..." << m_num1 % m_num2 << endl;
		return ;
	}
};

void test() {
	//创建加法
	abs_cacul* abs = new add_cacul;	//实例化对象
	abs->getresult(5, 2);
	delete abs;
	//创建减法
	abs = new sub_cacul;
	abs->getresult(5, 2);
	delete abs;
	//创建乘法
	abs = new mul_cacul;
	abs->getresult(5, 2);
	delete abs;
	//创建除法
	abs = new div_cacul;
	abs->getresult(5, 2);
	delete abs;
}

int main() {
	test();
	...
}

4.7.3 纯虚函数和抽象类

在这里插入图片描述

//只有一个纯虚函数的类为抽象类
class base {
public:
	virtual void func() = 0;
};

class son :public base {
public:
	virtual void func() {
		cout << "子类必须重写父类中的纯虚函数,否则无法实例化对象" << endl;
	}
};

void test() {
	base* base = new son; //创建对象
	base->func();
	delete base;
}

int main() {
	test();
	...
}

4.7.4 多态案例二 制作饮品

在这里插入图片描述

class make {
public:
	virtual void boil() = 0;
	virtual void brew() = 0;
	virtual void pour() = 0;
	virtual void puts() = 0;

	virtual void loop() {
		boil();
		brew();
		pour();
		puts();
	}
};

class coffee :public make {
public:
	virtual void boil() {
		cout << "	煮百岁山" << endl;
	}
	virtual void brew() {
		cout << "	冲泡咖啡" << endl;
	}
	virtual void pour() {
		cout << "	倒入马克杯" << endl;
	}
	virtual void puts() {
		cout << "	加糖和牛奶" << endl;
	}

	virtual void loop() {
		cout << "   来杯卡布奇诺:" << endl;
		boil();
		brew();
		pour();
		puts();
		cout << endl;
	}
};

class tea :public make {
public:
	virtual void boil() {
		cout << "	煮山泉水" << endl;
	}
	virtual void brew() {
		cout << "	冲泡茶叶" << endl;
	}
	virtual void pour() {
		cout << "	倒入紫砂壶" << endl;
	}
	virtual void puts() {
		cout << "	加菊和枸杞" << endl;
	}

	virtual void loop() {
		cout << "   来壶铁观音:" << endl;
		boil();
		brew();
		pour();
		puts();
		cout << endl;
	}
};

void do_drink(make* select) {
	select->loop();
	delete select; // 释放堆区数据
}

void test() {
	//制作咖啡
	do_drink(new coffee);
	//制作茶叶
	do_drink(new tea);
}

int main() {
	test();
	...
}

4.7.5 虚析构和纯虚析构

在这里插入图片描述
在这里插入图片描述

class animal {
public:
	virtual void speak() = 0;

	animal() {
		cout << "annimal的构造" << endl;
	}
	//虚析构会调用子类的析构函数
	//virtual ~animal() {
	//	cout << "annimal的虚析构" << endl;
	//}

	//纯虚析构 既需要声明 也需要实现
	virtual ~animal() = 0;
};

//纯虚析构的实现
animal::~animal() {
	cout << "annimal的纯虚析构" << endl;
}

class cat :public animal {
public:
	string* m_name;

	virtual void speak() {
		cout << *this->m_name << "cat在说话" << endl;
	}

	cat(string m_name) {
		cout << "cat的构造" << endl;
		this->m_name = new string(m_name);
	}

	 ~cat() {
		cout << "cat的析构" << endl;
		if (m_name != NULL) {
			delete m_name;
			m_name = NULL;
			return;
		}
	}
};

void test() {
	animal* animal = new cat("Tom");
	animal->speak();
	//父类指针在析构时,不会调用子类的的析构函数
	//利用虚析构解决
	delete animal;
}

int main() {
	test();
	...
}

在这里插入图片描述

4.7.6 多态案例三 电脑组装

在这里插入图片描述

//虚基类
class cpu {
public:
	virtual void cacul() = 0;
};
class memory {
public:
	virtual void storage() = 0;
};

//asua零件类
class asus_cpu :public cpu  {
public:
	virtual void cacul() {
		cout << "asus的cpu" << endl;
	}
};
class asus_mem :public memory{
public:
	virtual void storage() {
		cout << "asus的显卡" << endl;
	}
};

//lenovo零件类
class lenovo_cpu :public cpu {
public:
	virtual void cacul() {
		cout << "lenovo 的 cpu" << endl;
	}
};
class lenovo_mem : public memory{
public:
	virtual void storage() {
		cout << "lenovo 的显卡" << endl;
	}
};

//电脑组装
class computer {
public:
	cpu * m_cpu;
	memory * m_mem;
	
	computer(cpu* cpu ,memory* mem) {
		this->m_cpu = cpu;
		this->m_mem = mem;
	}

	~computer() {
		//释放cpu和内存条的零件指针
		if (m_cpu != null) {
			delete m_cpu;
			m_cpu = null;
		}
		if (m_mem != null) {
			delete m_mem;
			m_mem = null;
		}
		return;
	}

	void dowork() {
		m_cpu->cacul();
		m_mem->storage();
	}
};

void test() {
	cpu * cpu = new asus_cpu;
	memory * mem = new lenovo_mem;

	computer * c1 = new computer(cpu,mem);
	c1->dowork();
	delete c1;
}

int main() {
	test();
	...
}

5 文件操作

在这里插入图片描述

5.1 文本文件

5.1.1 写文件

在这里插入图片描述
在这里插入图片描述

void test() {
	ofstream ofs;
	
	ofs.open("C:/Users/yong/Desktop/test.txt", ios::out);
	
	ofs << "test1" << endl;
	ofs << "test2" << endl;
	
	ofs.close();
}

int main() {
	test();
	...
}

5.1.2 读文件

在这里插入图片描述

void test() {
	ifstream ifs;
	
	ifs.open("C:/Users/yong/Desktop/test.txt", ios::in);
	if (!ifs.is_open()) {
		cout << "test.txt打开失败!!!" << endl;
		return;
	}

	//读数据
	//第一种
	/*char buf[1024] = { 0 };
	while (ifs >> buf) {
		cout << buf << endl;
	}*/
	//第二种
	/*char buf[1024] = { 0 };
	while (ifs.getline(buf, sizeof(buf))) {
		cout << buf << endl;
	}*/
	//第三种
	string buf;
	while (getline(ifs, buf)) {
		cout << buf << endl;
	}
	//第四种 不常用 一个一个读 效率低
	/*char c;
	while ((c = ifs.get()) != EOF) { //EOF:end of file 文件尾的标志
		cout << c << endl;
	}*/

	ifs.close();
}

int main() {
	test();
	...
}

5.2 二进制文件

在这里插入图片描述

5.2.1 写文件

在这里插入图片描述

class person {
public:
	char m_name[64];
	int m_age;
};

void test() {
	ofstream ofs;
	
	ofs.open("C:/Users/yong/Desktop/test2.txt", ios::out | ios::binary);
	
	person p1 = { "张三", 18 };
	ofs.write((const char*)&p1, sizeof(p1));
	
	ofs.close();
}

int main() {
	test();
	...
}

在这里插入图片描述

5.2.2 读文件

在这里插入图片描述

class person {
public:
	char m_name[64];
	int m_age;
};

void test() {
	ifstream ifs;
	
	ifs.open("C:/Users/yong/Desktop/test2.txt", ios::in | ios::binary);
	if (!ifs.is_open()) {
		cout << "test2.txt打开失败!!!" << endl;
		return;
	}
	
	person p;
	ifs.read((char*)&p, sizeof(p));
	cout << p.m_name << "\t" <<p.m_age << endl;
	
	ifs.close();
}


int main() {
	test();
	...
}
  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值