#include<iostream>

using namespace std;

//内存分区模型
//代码区,存放二进制代码,由操作系统进行管理
//全局区,存放全局变量、静态变量、常量(字符串常量和const修饰的全局常量)
//栈区,存放函数参数值、局部变量等,由编译器自动分配释放
//堆区,由程序员分配和释放,若程序员不,程序结束时由操作系统回收
//内存四区意义,不同区域存放的数据赋予不同的生命周期,给我们更大的灵活编程 //程序运行前:代码区,全局区
//程序运行后:栈区,堆区 //全局变量
int g_a = ;
int g_b = ; //const修饰的全局常量
const int c_g_a = ;
const int c_g_b = ; int main()
{
//局部变量
int a = ;
int b = ;
cout << "局部变量地址为 " << (int)&a << endl;
cout << "局部变量地址为 " << (int)&b << endl;
cout << "全局变量地址为 " << (int)&g_a << endl;
cout << "全局变量地址为 " << (int)&g_b << endl; //静态变量
static int s_a = ;
static int s_b = ;
cout << "静态变量地址为 " << (int)&s_a << endl;
cout << "静态变量地址为 " << (int)&s_b << endl; //字符串常量
string s1 = "s1";
string s2 = "s2";
cout << "字符串常量地址为 " << (int)&s1 << endl;
cout << "字符串常量地址为 " << (int) & "s2" << endl; //const修饰的全局常量
cout << "const修饰的全局常量 " << (int)&c_g_a << endl;
cout << "const修饰的全局常量 " << (int)&c_g_b << endl; //const修饰的局部常量
const int c_l_a = ;
const int c_l_b = ;
cout << "const修饰的局部常量 " << (int)&c_l_a << endl;
cout << "const修饰的局部常量 " << (int)&c_l_b << endl; system("pause"); return ;
}

内存分区模型

传智播客C++视频学习笔记(3)-LMLPHP

#include<iostream>

using namespace std;

int* func(int b) //形参数据也会存放在栈区
{
int a = ;
return &a; //不要返回局部变量的地址,局部变量存放在栈区,栈区开辟的数据由编译器自动释放
} int main()
{
int* p = func(); cout << *p << endl; //第一次打印正确,是因为编译器做了保留
cout << *p << endl; //第二次打印错误 system("pause"); return ;
}

栈区

#include<iostream>

using namespace std;

int* func()
{
int* p = new int(); //利用new关键字可以将数据开辟到堆区
return p; //指针本质上也是局部变量,放在栈上,但指针保存的数据是放在堆区
} //栈:int* p 0x0011
//堆:0x0011 10
int main()
{
int* p = func(); cout << *p << endl;
cout << *p << endl; system("pause"); return ;
}

堆区

#include<iostream>

using namespace std;

int* func()
{
int* p = new int();
return p;
} int main()
{
int* p = func(); cout << *p << endl;
cout << *p << endl; delete p; //cout << *p << endl; //报错
cout << "------------------------------------" << endl; //堆区开辟数组 int* arr = new int[]; for (int i = ; i < ; i++)
{
arr[i] = i + ;
} for (int i = ; i < ; i++)
{
cout << arr[i] << endl;
} delete[] arr; system("pause"); return ;
}

new操作符

#include<iostream>

using namespace std;

int main()
{
int a = ;
int& b = a; //给变量起别名 cout << "a = " << a << endl;
cout << "b = " << b << endl; b = ; cout << "a = " << a << endl;
cout << "b = " << b << endl; system("pause"); return ;
}

引用的基本使用

#include<iostream>

using namespace std;

int main()
{ int a = ;
int b = ; //引用必须初始化
//int& c; //引用初始化后不可以改变
int& c = a;
c = b; //这是赋值操作 cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl; system("pause"); return ;
}

引用注意事项

#include<iostream>

using namespace std;

//值传递
void mySwap01(int a, int b)
{
int temp = a;
a = b;
b = temp;
} //地址传递
void mySwap02(int* p1, int* p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
} //引用传递
void mySwap03(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
} int main()
{
int a = ;
int b = ; //mySwap01(a, b); //mySwap02(&a, &b); mySwap03(a, b); cout << "a = " << a << endl;
cout << "b = " << b << endl; system("pause"); return ;
}

引用做函数参数

#include<iostream>

using namespace std;

//返回局部变量引用
int& test01()
{
int a = ;
return a;
} //返回静态变量引用
int& test02()
{
static int a = ;
return a;
} int main()
{
//不要返回局部变量引用
int& ref = test01();
cout << "ref = " << ref << endl;
cout << "ref = " << ref << endl; //返回静态变量引用
int& ref2 = test02();
cout << "ref2 = " << ref2 << endl;
cout << "ref2 = " << ref2 << endl; //函数调用作为左值,必须返回引用
test02() = ;
cout << "ref2 = " << ref2 << endl;
cout << "ref2 = " << ref2 << endl; system("pause"); return ;
}

引用做函数返回值

#include<iostream>

using namespace std;

void func(int& ref)
{
ref = ;
} int main()
{
int a = ; //引用本质是在C++内部实现一个指针常量
//指针常量,指针指向不可以修改,即引用不可以修改
//int* const ref = &a;
int& ref = a; //*ref = 20;
ref = ; cout << "a = " << a << endl;
cout << "ref = " << ref << endl; func(a); cout << "a = " << a << endl;
cout << "ref = " << ref << endl; system("pause"); return ;
}

引用的本质

#include<iostream>

using namespace std;

//常量引用通常用来修饰形参
void showValue(const int& v)
{
//v += 10;
cout << "v = " << v << endl;
} int main()
{
//常量引用主要用来修饰形参,防止误操作,即防止形参改变实参 //错误,需要加一个const修饰
//int& ref = 10; //int temp = 10; const int& ref = temp;
const int& ref = ; //ref = 100; //不可以修改 //函数中利用常量引用防止误操作修改实参
int a = ;
showValue(a); system("pause"); return ;
}

常量引用

#include<iostream>

using namespace std;

//函数参数某个位置有默认值,那么从这个位置往后,从左到右,必须都要有默认值
int func(int a, int b = , int c = )
{
return a + b + c;
} //如果函数声明有默认值,函数实现就不能有默认值,二者冲突
///函数声明
int func2(int a = , int b = );
//函数实现
int func2(int a, int b)
{
return a + b;
} int main()
{
cout << "return = " << func(, ) << endl; // cout << "return = " << func2(, ) << endl; // system("pause"); return ;
}

函数默认参数

#include<iostream>

using namespace std;

//函数占位参数,也可以有默认值
void func(int a, int)
{
cout << "this is func" << endl;
} int main()
{
func(, ); system("pause"); return ;
}

函数占位参数

#include<iostream>

using namespace std;

//函数重载条件:
//同一作用域下
//函数名称相同
//函数参数类型不同、个数不同、顺序不同
//注:函数返回值不同不可以作为函数重载的满足条件 void func()
{
cout << "func()调用" << endl;
} void func(int a)
{
cout << "func(int a)调用" << endl;
} void func(double d)
{
cout << "func(double d)调用" << endl;
} void func(int a, double d)
{
cout << "func(int a, double d)调用" << endl;
} void func(double d, int a)
{
cout << "func(double d, int a)调用" << endl;
} int main()
{
func();
func();
func(1.1);
func(, 1.1);
func(1.1, ); system("pause"); return ;
}

函数重载概述

#include<iostream>

using namespace std;

//引用作为重载条件
void func(int& a)
{
cout << "func(int& a)调用" << endl;
}
void func(const int& a)
{
cout << "func(const int& a)调用" << endl;
} //函数重载碰到函数默认参数
void func2(int a, int b = )
{
cout << "func2(int a, int b = 10)调用" << endl;
}
void func2(int a)
{
cout << "func2(int a)调用" << endl;
} int main()
{
int a = ;
func(a); //调用无const
func(); //调用有const func2(, ); //此处填一个参数会产生歧义 system("pause"); return ;
}

函数重载注意事项

#include<iostream>

using namespace std;

//类和对象
//面向对象三大特征:封装、继承、多态
//万物皆对象,对象有属性和行为
//车类,车
//? //设计一个圆类求其周长
const double PI = 3.14;
class Circle
{
public: int r; double zhouChang()
{
return * PI * r;
}
}; int main()
{
Circle c;
c.r = ;
cout << "圆的周长 = " << c.zhouChang() << endl; system("pause"); return ;
}

封装意义(1)

#include<iostream>

using namespace std;

class Student
{
public: string m_name;
int m_id; void setName(string name)
{
m_name = name;
} void setId(int id)
{
m_id = id;
} void showStudent()
{
cout << "name = " << m_name << " " << "id = " << m_id << endl;
}
}; int main()
{
Student s;
s.m_name = "张三";
s.m_id = ;
//s.setName("李四");
s.showStudent(); system("pause"); return ;
}

学生类示例

#include<iostream>

using namespace std;

//public 公共权限,类内类外均可以访问
//protected 保护权限,类内可以访问类外不可以访问
//private 私有权限,类内可以访问类外不可以访问 class Preson
{
public:
string m_name; protected:
string m_car; private:
int m_passWord;
}; int main()
{
Preson p;
p.m_name = "张三";
//p.m_car;
//p.m_passWord; system("pause"); return ;
}

封装意义(2)

#include<iostream>

using namespace std;

class C1
{
//默认为私有权限
int m_c1;
}; struct C2
{
//默认为公共权限
int m_c2;
}; int main()
{ C1 c1;
//c1.m_c1; C2 c2;
c2.m_c2 = ; system("pause"); return ;
}

class与struct区别

#include<iostream>

using namespace std;

class Preson
{
private:
string m_name; int m_age; string m_lover; public:
void setName(string name)
{
m_name = name;
} string getName()
{
return m_name;
} void setAge(int age)
{
if (age < || age > )
{
cout << "你是妖精吧" << endl;
}
m_age = age;
} void setLover(string lover)
{
m_lover = lover;
} string getLover()
{
return m_lover;
}
}; int main()
{
Preson p;
p.setName("张三");
cout << "m_name = " << p.getName() << endl;
p.setAge();
p.setLover("波多野结衣");
cout << "m_lover = " << p.getLover() << endl; system("pause"); return ;
}

成员属性设置为私有

#include<iostream>

using namespace std;

#include "point.h"
#include "circle.h" //判断点和圆关系的全局函数
void isInCircle(Circle& c, Point& p)
{
//两点之间距离^2
int ppDistance =
(c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +
(c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY()); //半径^2
int rDistance = c.getR() * c.getR(); //判断
if (ppDistance == rDistance)
{
cout << "点在圆上" << endl;
}
else if (ppDistance > rDistance)
{
cout << "点在圆外" << endl;
}
else
{
cout << "点在圆内" << endl;
}
} int main()
{
//设置圆,半径为10,圆心坐标为(10,0)
Circle c;
c.setR();
Point center;
center.setX();
center.setY();
c.setCenter(center); //设置点
Point p;
p.setX();
p.setY(); //判断
isInCircle(c, p); system("pause"); return ;
}

判断点和圆的位置关系

#pragma once

#include <iostream>
using namespace std; class Point
{
private:
//坐标X
int m_x;
//坐标Y
int m_y;
public:
//设置X
void setX(int x);
//获取X
int getX();
//设置Y
void setY(int y);
//获取Y
int getY();
};

point.h

#include "point.h"

//设置X
void Point::setX(int x)
{
m_x = x;
} //获取X
int Point::getX()
{
return m_x;
} //设置Y
void Point::setY(int y)
{
m_y = y;
} //获取Y
int Point::getY()
{
return m_y;
}

point.cpp

#pragma once

#include <iostream>
using namespace std; #include "point.h" class Circle
{
private:
//半径
int m_r;
//圆心,类中有类
Point m_center;
public:
//设置半径
void setR(int r);
//获取半径
int getR();
//设置圆心
void setCenter(Point center);
//获取圆心
Point getCenter();
};

circle.h

#include "circle.h"

//设置半径
void Circle::setR(int r)
{
m_r = r;
} //获取半径
int Circle::getR()
{
return m_r;
} //设置圆心
void Circle::setCenter(Point center)
{
m_center = center;
} //获取圆心
Point Circle::getCenter()
{
return m_center;
}

circle.cpp

#include <iostream>

using namespace std;

//构造函数:创建对象时为对象成员属性赋值,由编译器自动调用

//析构函数:对象销毁前系统自动调用

//构造函数语法:
//没有返回值也不写void
//函数名与类名相同
//可以有参数,因此可以发生重载
//程序调用对象时会自动调用构造,无需手动调用且只会调用一次 //析构函数语法:
//没有返回值也不写void
//函数名与类名相同,前面加~
//不可以有参数,因此不可以发生重载
//对象销毁前会自动调用析构,无需手动调用且只会调用一次 class Preson
{
public:
//构造函数
Preson()
{
cout << "Preson构造函数调用" << endl;
}
//析构函数
~Preson()
{
cout << "Preson析构函数调用" << endl;
}
}; void test01()
{
Preson p;
} int main()
{
test01(); system("pause"); return ;
}

构造函数和析构函数

#include <iostream>

using namespace std;

//按参数分:有参构造,无参构造
//按类型分:普通构造,拷贝构造 //三种调用方式:括号法,显示法,隐式转换法 class Preson
{
public:
int age;
public:
//无参(默认)构造函数
Preson()
{
cout << "无参构造函数调用" << endl;
}
//有参构造函数
Preson(int a)
{
age = a;
cout << "有参构造函数调用" << endl;
}
//拷贝构造函数
Preson(const Preson& p)
{
age = p.age;
cout << "拷贝构造函数调用" << endl; }
//析构函数
~Preson()
{
cout << "析构函数调用" << endl;
}
}; //调用无参构造函数
void test01()
{
Preson p;
} //调用有参构造函数
void test02()
{
//括号法
Preson p1();
//Preson p2(); //调用无参构造函数不要这样写,编译器会认为是函数声明 //显示法
Preson p2 = Preson();
Preson p3 = Preson(p2);
//Preson(10) //这是匿名对象,当前行结束之后马上析构 //隐式转换法
Preson p4 = ; //Preson p4 = Preson(10);
Preson p5 = p4; //Preson p5 = Preson(p4);
//Preson p5(p4); //不能利用拷贝构造函数初始化匿名对象,编译器会认为是函数声明
} int main()
{
//test01(); test02(); system("pause"); return ;
}

构造函数分类及调用

#include <iostream>

using namespace std;

//拷贝构造函数调用三种情况:
//使用一个已经创建完毕的对象初始化一个新对象
//值传递方式给函数参数传值
//值传递方式返回局部对象 class Preson
{
public:
int age;
public:
//无参(默认)构造函数
Preson()
{
age = ;
cout << "无参构造函数调用" << endl;
}
//有参构造函数
Preson(int a)
{
age = a;
cout << "有参构造函数调用" << endl;
}
//拷贝构造函数
Preson(const Preson& p)
{
age = p.age;
cout << "拷贝构造函数调用" << endl; }
//析构函数
~Preson()
{
cout << "析构函数调用" << endl;
}
}; //使用一个已经创建完毕的对象初始化一个新对象
void test01()
{
Preson p1();
Preson p2(p1);
Preson p3 = p1;
} //值传递方式给函数参数传值
void doWork01(Preson p)
{ }
void test02()
{
Preson p;
doWork01(p);
} //值传递方式返回局部对象
Preson doWork02()
{
Preson p;
cout << (int)&p << endl;
return p;
}
void test03()
{
Preson p = doWork02();
cout << (int)&p << endl;
} int main()
{
//test01(); //test02(); test03(); system("pause"); return ;
}

拷贝构造函数调用时机

#include <iostream>

using namespace std;

//默认情况下,C++编译器至少给一个类添加三个函数
//默认无参构造函数
//默认析构函数
//默认拷贝构造函数 //若用户定义有参构造函数,C++编译器不再提供默认无参构造函数,但会提供默认拷贝构造函数
//若用户定义拷贝构造函数,C++编译器什么也不提供 class Preson
{
public:
int age;
public:
//无参(默认)构造函数
Preson()
{
cout << "无参构造函数调用" << endl;
}
//有参构造函数
Preson(int a)
{
age = a;
cout << "有参构造函数调用" << endl;
}
//拷贝构造函数
Preson(const Preson& p)
{
age = p.age;
cout << "拷贝构造函数调用" << endl; }
//析构函数
~Preson()
{
cout << "析构函数调用" << endl;
}
}; void test01()
{
Preson p1();
Preson p2(p1); //若不写拷贝构造函数,C++编译器会自动添加并做浅拷贝操作
cout << "p2年龄 = " << p2.age << endl;
} void test02()
{
Preson p1;
Preson p2();
Preson p3(p2); Preson p4;
Preson p5();
Preson p6(p5);
} int main()
{
//test01(); test02(); system("pause"); return ;
}

构造函数调用规则

#include <iostream>

using namespace std;

//浅拷贝:简单的赋值拷贝操作
//深拷贝:在堆区重新申请空间进行拷贝操作 class Preson
{
public:
int m_age;
int* m_hieght;
public:
//无参(默认)构造函数
Preson()
{
cout << "无参构造函数调用" << endl;
}
//有参构造函数
Preson(int age, int height)
{
m_age = age;
m_hieght = new int(height);
cout << "有参构造函数调用" << endl;
}
//拷贝构造函数
Preson(const Preson& p)
{
m_age = p.m_age;
m_hieght = new int(*p.m_hieght); //如果类属性是在堆区开辟的,一定要自己提供拷贝函数,防止浅拷贝带来的问题
cout << "拷贝构造函数调用" << endl; //如果不利用深拷贝在堆区创建新内存,会导致浅拷贝带来重复释放堆区问题
}
//析构函数
~Preson()
{
if (m_hieght != NULL)
{
delete m_hieght;
}
cout << "析构函数调用" << endl;
}
}; void test01()
{
Preson p1(, );
Preson p2(p1);
cout << "p1年龄 = " << p1.m_age << endl;
cout << "p1体重 = " << *p1.m_hieght << endl;
cout << "p2年龄 = " << p2.m_age << endl;
cout << "p2体重 = " << *p2.m_hieght << endl;
} int main()
{
test01(); system("pause"); return ;
}

浅拷贝与深拷贝

#include <iostream>

using namespace std;

class Preson
{
private:
int m_a;
int m_b;
int m_c;
public:
//传统方式
/*Preson(int a, int b, int c)
{
m_a = a;
m_b = b;
m_c = c;
}*/ Preson(int a, int b, int c) :m_a(a), m_b(b), m_c(c)
{ } void printPreson()
{
cout << "mA = " << m_a << endl;
cout << "mB = " << m_b << endl;
cout << "mC = " << m_c << endl;
}
}; int main()
{
Preson p(, , );
p.printPreson(); system("pause"); return ;
}

初始化列表

#include <iostream>

using namespace std;

//类1中包含另一个类2时,
//构造函数先执行类2在执行类1
//析构函数先执行类1在执行类2 class Phone
{
public:
string m_phoneName;
public:
Phone(string name)
{
m_phoneName = name;
cout << "Phone构造函数" << endl;
}
~Phone()
{
cout << "Phone析构函数" << endl;
}
}; class Preson
{
public:
string m_name;
Phone m_phoneNmae;
public:
Preson(string name, string pname) :m_name(name), m_phoneNmae(pname)
{
cout << "Preson构造函数" << endl;
}
~Preson()
{
cout << "Preson析构函数" << endl;
}
void playShow()
{
cout << m_name << " 使用 " << m_phoneNmae.m_phoneName << " 牌子手机" << endl;
}
}; void test01()
{
Preson p("张三", "IphoneX");
p.playShow();
} int main()
{
test01(); system("pause"); return ;
}

类中有类

#include <iostream>

using namespace std;

//静态成员变量:
//所有对象共享同一份数据
//在编译阶段分配内存
//类内声明类外初始化 class Preson
{
public:
static int m_a;
private:
static int m_b;
}; int Preson::m_a = ;
int Preson::m_b = ; void test01()
{
//通过对象访问
Preson p1;
p1.m_a = ;
cout << "p1.m_a " << p1.m_a << endl; //共享同一份数据
Preson p2;
p2.m_a = ;
cout << "p1.m_a " << p1.m_a << endl;
cout << "p2.m_a " << p2.m_a << endl; //通过类名访问
cout << "m_a " << Preson::m_a << endl; //cout << "m_b " << Preson::m_b << endl; //私有权限访问不到
} int main()
{
test01(); system("pause"); return ;
}

静态成员变量

#include <iostream>

using namespace std;

//静态成员函数:
//所有对象共享同一个函数
//静态成员函数只能访问静态成员变量 class Preson
{
public:
static int m_a;
int m_b;
public:
static void func1()
{
m_a = ;
//m_b = 100;
cout << "func1()调用" << endl;
}
private:
static void func2()
{
cout << "func2()调用" << endl;
}
}; int Preson::m_a = ; void test01()
{
//通过对象访问
Preson p1;
p1.func1(); //通过类名访问
Preson::func1(); //Preson::func2();
} int main()
{
test01(); system("pause"); return ;
}

静态成员函数

#include <iostream>

using namespace std;

//在C++中,类的成员变量和成员函数分开存储
//只有非静态成员变量占对象空间 class Preson
{
public:
Preson()
{ } int m_a; /*static int m_b; void func1()
{ } static void func2()
{ }*/
}; int main()
{
cout << sizeof(Preson) << endl; system("pause"); return ;
}

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

#include <iostream>

using namespace std;

//this指针指向被调用成员函数所属的对象
//this指针是隐含在每一个非静态成员函数内的一种指针
//this指针不需要定义,直接使用即可 //this指针用途:
//1、当形参和成员变量重名时,可以用this指针来区分
//2、在类的非静态成员函数中返回对象本身,可使用return *this class Preson
{ public:
int age;
public:
Preson(int age)
{
//1、
this->age = age;
}
//2、
Preson& presonAdd(Preson p)
{
this->age += p.age;
return *this;
}
}; void test01()
{
Preson p1();
cout << "p1.age = " << p1.age << endl; Preson p2();
p2.presonAdd(p1).presonAdd(p1).presonAdd(p1);
cout << "p2.age = " << p2.age << endl;
} int main()
{
test01(); system("pause"); return ;
}

this指针概念

#include <iostream>

using namespace std;

class Preson
{
public:
int m_age;
public:
void showClassName()
{
cout << "我是showClassName()" << endl;
}
void showPreson()
{
if (this == NULL)
{
return;
}
cout << "我是showPreson()" << endl;
}
}; void test01()
{
Preson* p = NULL;
p->showClassName();
p->showPreson();
} int main()
{
test01(); system("pause"); return ;
}

空指针访问成员函数

#include <iostream>

using namespace std;

//成员函数后加const称为常函数
//常函数内不可以修改成员属性
//成员属性在声明时加mutable关键字后,在常函数中依然可以修改 //声明对象前加const称为常对象
//常对象只能调用常函数 class Preson
{
public:
int m_a;
mutable int m_b;
public:
Preson()
{
m_a = ;
m_b = ;
}
//this指针本质为一个指针常量,指针指向不可以修改
//如果想指针指向的值也不可以修改,需声明常函数
void func1() const
{
//this = NULL; //不能修改指针指向 //this->m_a = 100; //不能修改指针指向的值 this->m_b = ;
}
}; void test01()
{
//常对象
const Preson p;
//p.m_a = 100;
p.m_b = ;
p.func1();
} int main()
{
test01(); system("pause"); return ;
}

常函数和常对象

#include <iostream>

using namespace std;

//全局函数做友元

class Building
{
friend void goodGay(Building* b); public:
string m_SittingRoom;
private:
string m_BedRoom;
public:
Building()
{
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
}
}; void goodGay(Building* b)
{
cout << "好基友正在访问:" << b->m_SittingRoom << endl;
cout << "好基友正在访问:" << b->m_BedRoom << endl;
} void test01()
{
Building b;
goodGay(&b);
} int main()
{
test01(); system("pause"); return ;
}

全局函数做友元

#include <iostream>

using namespace std;

//类做友元

class Building;

class GoodGay
{
private:
Building* b;
public:
GoodGay();
void visit();
}; class Building
{
friend class GoodGay; public:
string m_SittingRoom;
private:
string m_BedRoom;
public:
Building();
}; Building::Building()
{
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
} GoodGay::GoodGay()
{
b = new Building;
} void GoodGay::visit()
{
cout << "好基友正在访问:" << b->m_SittingRoom << endl;
cout << "好基友正在访问:" << b->m_BedRoom << endl;
} void test01()
{
GoodGay gg;
gg.visit();
} int main()
{
test01(); system("pause"); return ;
}

类做友元

#include <iostream>

using namespace std;

//成员函数做友元

class Building;

class GoodGay
{
private:
Building* b;
public:
GoodGay();
void visit();
void visit2();
}; class Building
{
friend void GoodGay::visit(); public:
string m_SittingRoom;
private:
string m_BedRoom;
public:
Building();
}; Building::Building()
{
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
} GoodGay::GoodGay()
{
b = new Building;
} void GoodGay::visit()
{
cout << "好基友正在访问:" << b->m_SittingRoom << endl;
cout << "好基友正在访问:" << b->m_BedRoom << endl;
} void GoodGay::visit2()
{
cout << "好基友正在访问:" << b->m_SittingRoom << endl;
//cout << "好基友正在访问:" << b->m_BedRoom << endl;
} void test01()
{
GoodGay gg;
gg.visit();
gg.visit2();
} int main()
{
test01(); system("pause"); return ;
}

成员函数做友元

#include <iostream>

using namespace std;

//加号运算符重载
//实现两个自定义数据类型相加运算 class Preson
{
public:
int m_a;
int m_b;
public:
Preson()
{ }
Preson(int a, int b)
{
this->m_a = a;
this->m_b = b;
}
//成员函数实现
/*Preson operator+(Preson& p)
{
Preson val;
val.m_a = this->m_a + p.m_a;
val.m_b = this->m_b + p.m_b;
return val;
}*/
}; //全局函数实现
Preson operator+(Preson& p1, Preson& p2)
{
Preson val(, );
val.m_a = p1.m_a + p2.m_a;
val.m_b = p1.m_b + p2.m_b;
return val;
} //运算符重载的同时也可以发生函数重载
Preson operator+(Preson& p1, int n)
{
Preson val(, );
val.m_a = p1.m_a + n;
val.m_b = p1.m_b + n;
return val;
} void test01()
{
Preson p1(, );
Preson p2(, ); Preson p3 = p1 + p2; Preson p4 = p3 + ; cout << "m_a = " << p3.m_a << endl;
cout << "m_b = " << p3.m_b << endl; cout << "m_a = " << p4.m_a << endl;
cout << "m_b = " << p4.m_b << endl;
} int main()
{
test01(); system("pause"); return ;
}

加号运算符重载

#include <iostream>

using namespace std;

//左移运算符重载
//可以输出自定义数据类型 class Preson
{
friend ostream& operator<<(ostream& cout, Preson& p); private:
int m_a;
int m_b;
public:
Preson(int a, int b)
{
this->m_a = a;
this->m_b = b;
}
//成员函数实现不了
//p << cout 不是我们想要的格式
}; //全局函数实现
ostream& operator<<(ostream& out, Preson& p)
{
out << "m_a = " << p.m_a << endl;
out << "m_b = " << p.m_b << endl;
return out;
} void test01()
{
Preson p(, );
cout << p << endl; //链式编程
} int main()
{
test01(); system("pause"); return ;
}

左移运算符重载

#include <iostream>

using namespace std;

//递增运算符重载

class myInt
{
friend ostream& operator<<(ostream& out, myInt mi); private:
int m_num;
public:
myInt()
{
m_num = ;
}
//前置++
myInt& operator++()
{
//先++在return
m_num++;
return *this;
}
//后置++
myInt operator++(int)
{
//先return在++
myInt mi = *this;
m_num++;
return mi;
}
}; ostream& operator<<(ostream& out, myInt mi)
{
out << mi.m_num;
return out;
} //前置++
void test01()
{
myInt mi;
cout << ++mi << endl;
cout << mi << endl;
} //后置++
void test02()
{
myInt mi;
cout << mi++ << endl;
cout << mi << endl;
} int main()
{
test01(); test02(); system("pause"); return ;
}

递增运算符重载

#include <iostream>

using namespace std;

//赋值运算符重载

class Preson
{
public:
int* m_age;
public:
Preson(int age)
{
m_age = new int(age);
}
Preson& operator=(Preson& p)
{
if (m_age != NULL)
{
delete m_age;
m_age = NULL;
} //编译器提供的是浅拷贝
//m_age = p.m_age; //深拷贝
m_age = new int(*p.m_age);
return *this;
}
~Preson()
{
if (m_age != NULL)
{
delete m_age;
m_age = NULL;
}
}
}; void test01()
{
Preson p1();
Preson p2();
Preson p3(); p3 = p2 = p1; cout << "p1年龄 = " << *p1.m_age << endl;
cout << "p2年龄 = " << *p2.m_age << endl;
cout << "p3年龄 = " << *p3.m_age << endl;
} int main()
{
test01(); int a = ;
int b = ;
int c = ; c = b = a; cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl; system("pause"); return ;
}

赋值运算符重载

#include <iostream>

using namespace std;

//关系运算符重载

class Preson
{
public:
string m_name;
int m_age;
public:
Preson(string name, int age)
{
this->m_name = name;
this->m_age = age;
}
bool operator==(Preson& p)
{
if (this->m_name == p.m_name && this->m_age == p.m_age)
{
return true;
}
else
{
return false;
}
}
bool operator!=(Preson& p)
{
if (this->m_name == p.m_name && this->m_age == p.m_age)
{
return false;
}
else
{
return true;
}
}
}; void test01()
{
Preson p1("张三", );
Preson p2("张三", ); if (p1 == p2)
{
cout << "p1==p2" << endl;
}
else
{
cout << "p1!=p2" << endl;
} if (p1 != p2)
{
cout << "p1!=p2" << endl;
}
else
{
cout << "p1==p2" << endl;
}
} int main()
{
test01(); system("pause"); return ;
}

关系运算符重载

#include <iostream>

using namespace std;

//函数调用运算符重载
//也称为仿函数(),没有固定写法,非常灵活 class myPrint
{
public:
void operator()(string s)
{
cout << s << endl;
}
}; void test01()
{
myPrint mp;
mp("hello world");
} class myAdd
{
public:
int operator()(int a, int b)
{
return a + b;
}
}; void test02()
{
myAdd ma;
int n = ma(, );
cout << "n = " << n << endl; //匿名对象调用
cout << "myAdd()(1000, 1000) = " << myAdd()(, ) << endl;
} int main()
{
test01(); test02(); system("pause"); return ;
}

函数调用运算符重载

#include <iostream>

using namespace std;

//继承:减少重复代码

//子类,父类
//派生类,基类 class basePage
{
public:
void header()
{
cout << "公共头部" << endl;
}
void footer()
{
cout << "公共底部" << endl;
}
}; class Java :public basePage
{
public:
void concent()
{
cout << "Java学习视频" << endl;
}
}; class Python :public basePage
{
public:
void concent()
{
cout << "Python学习视频" << endl;
}
}; class CPP :public basePage
{
public:
void concent()
{
cout << "CPP学习视频" << endl;
}
}; void test01()
{
Java ja;
ja.header();
ja.footer();
ja.concent(); Python py;
py.header();
py.footer();
py.concent(); CPP cp;
cp.header();
cp.footer();
cp.concent();
} int main()
{
test01(); system("pause"); return ;
}

继承基本语法

#include <iostream>

using namespace std;

//公有继承
class Base1
{
public:
int m_a;
protected:
int m_b;
private:
int m_c;
};
class Son1 :public Base1
{
void func()
{
m_a; //可访问,public权限
m_b; //可访问,protected权限
//m_c; //不可访问
}
};
void test01()
{
Son1 s1;
s1.m_a;
} //保护继承
class Base2
{
public:
int m_a;
protected:
int m_b;
private:
int m_c;
};
class Son2 :protected Base2
{
void func()
{
m_a; //可访问,protected权限
m_b; //可访问,protected权限
//m_c; //不可访问
}
};
void test02()
{
Son2 s2;
} //私有继承
class Base3
{
public:
int m_a;
protected:
int m_b;
private:
int m_c;
};
class Son3 :private Base3
{
void func()
{
m_a; //可访问,private权限
m_b; //可访问,private权限
//m_c; //不可访问
}
};
void test03()
{
Son3 s3;
} int main()
{
test01(); test02(); test03(); system("pause"); return ;
}

继承方式

#include <iostream>

using namespace std;

//父类中私有成员也被子类继承了,只是被编译器隐藏访问不到

class Base
{
public:
int m_a;
protected:
int m_b;
private:
int m_c;
}; class Son :public Base
{
public:
int m_d;
}; void test01()
{
cout << sizeof(Son) << endl; //
} int main()
{
test01(); system("pause"); return ;
}

继承中的对象模型

#include <iostream>

using namespace std;

//继承中先调用父类构造函数,在调用子类构造函数
//析构函数与构造函数调用顺序相反 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 test01()
{
Son s;
} int main()
{
test01(); system("pause"); return ;
}

继承中构造函数与析构函数调用顺序

#include <iostream>

using namespace std;

//子类对象可以直接访问子类同名成员
//子类对象加作用域可以访问父类同名成员
//子类和父类有同名成员函数时,子类会隐藏父类同名成员函数,若想访问需加作用域 class Base
{
public:
int m_a;
public:
Base()
{
m_a = ;
}
void func()
{
cout << "Base func()调用" << endl;
}
void func(int a)
{
cout << "Base func(int a)调用" << endl;
}
}; class Son :public Base
{
public:
int m_a;
public:
Son()
{
m_a = ;
}
void func()
{
cout << "Son func()调用" << endl;
}
}; void test01()
{
Son s;
cout << "Son的m_a = " << s.m_a << endl;
cout << "Base的m_a = " << s.Base::m_a << endl; s.func();
s.Base::func();
s.Base::func();
} int main()
{
test01(); system("pause"); return ;
}

继承中同名成员处理方式

#include <iostream>

using namespace std;

class Base
{
public:
static int m_a;
public:
static void func()
{
cout << "Base func()调用" << endl;
}
static void func(int a)
{
cout << "Base func(int a)调用" << endl;
}
}; int Base::m_a = ; class Son :public Base
{
public:
static int m_a;
public:
static void func()
{
cout << "Son func()调用" << endl;
}
}; int Son::m_a = ; //同名成员属性
void test01()
{
//通过对象访问
Son s;
cout << "Son的m_a = " << s.m_a << endl;
cout << "Base的m_a = " << s.Base::m_a << endl; //通过类名访问
cout << "Son的m_a = " << Son::m_a << endl;
cout << "Base的m_a = " << Son::Base::m_a << endl;
} //同名成员函数
void test02()
{
//通过对象访问
Son s;
s.func();
s.Base::func(); //通过类名访问
Son::func();
//Base::代表作用域
Son::Base::func();
Son::Base::func();
} int main()
{
test01(); test02(); system("pause"); return ;
}

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

#include <iostream>

using namespace std;

class Base1
{
public:
int m_a;
public:
Base1()
{
m_a = ;
}
}; class Base2
{
public:
int m_a;
public:
Base2()
{
m_a = ;
}
}; class Son :public Base1, public Base2
{
public:
int m_c;
int m_d;
public:
Son()
{
m_c = ;
m_d = ;
}
}; void test01()
{
Son s;
cout << sizeof(Son) << endl;
cout << s.Base1::m_a << endl;
cout << s.Base2::m_a << endl;
} int main()
{
test01(); system("pause"); return ;
}

多继承语法

#include <iostream>

using namespace std;

//菱形继承带来的主要问题是子类继承两份相同的数据,导致资源浪费且毫无意义
//利用虚继承解决菱形继承问题 class Animal
{
public:
int m_age;
}; class Yang :virtual public Animal
{ }; class Tuo :virtual public Animal
{ }; class YangTuo :public Yang, public Tuo
{ }; void test01()
{
YangTuo yt;
yt.Yang::m_age = ;
yt.Tuo::m_age = ; cout << "yt.Yang::m_age = " << yt.Yang::m_age << endl;
cout << "yt.Tuo::m_age = " << yt.Tuo::m_age << endl;
cout << "yt.m_age = " << yt.m_age << endl;
} int main()
{
test01(); system("pause"); return ;
}

菱形继承

#include <iostream>

using namespace std;

//多态满足条件:
//有继承关系
//子类重写父类中的虚函数 //多态使用条件
//父类指针或引用指向子类对象
//重写时,函数返回类型、函数名、参数列表要完全一致 class Animal
{
public:
//虚函数
virtual void speak()
{
cout << "动物在说话" << endl;
}
}; class Cat :public Animal
{
public:
void speak()
{
cout << "小猫在说话" << endl;
}
}; class Dog :public Animal
{
public:
void speak()
{
cout << "小狗在说话" << endl;
}
}; void doSpeak(Animal& a)
{
a.speak();
} void test01()
{
Cat cat;
doSpeak(cat); Dog dog;
doSpeak(dog);
} int main()
{
test01(); system("pause"); return ;
}

多态的基本概念

#include <iostream>

using namespace std;

class jiSuanQi
{
public:
int m_num1;
int m_num2;
public:
virtual int getResult()
{
return ;
}
}; class jiajiSuanQi :public jiSuanQi
{
public:
int getResult()
{
return m_num1 + m_num2;
}
}; class jianjiSuanQi :public jiSuanQi
{
public:
int getResult()
{
return m_num1 - m_num2;
}
}; class chengjiSuanQi :public jiSuanQi
{
public:
int getResult()
{
return m_num1 * m_num2;
}
}; class chujiSuanQi :public jiSuanQi
{
public:
int getResult()
{
return m_num1 / m_num2;
} }; void test01()
{
//加法
jiSuanQi* jsq = new jiajiSuanQi;
jsq->m_num1 = ;
jsq->m_num2 = ;
cout << "加法 = " << jsq->getResult() << endl;
delete jsq; //减法
jsq = new jianjiSuanQi;
jsq->m_num1 = ;
jsq->m_num2 = ;
cout << "减法 = " << jsq->getResult() << endl;
delete jsq; //乘法
jsq = new chengjiSuanQi;
jsq->m_num1 = ;
jsq->m_num2 = ;
cout << "乘法 = " << jsq->getResult() << endl;
delete jsq; //除法
jsq = new chujiSuanQi;
jsq->m_num1 = ;
jsq->m_num2 = ;
cout << "除法 = " << jsq->getResult() << endl;
delete jsq;
} int main()
{
test01(); system("pause"); return ;
}

多态计算器

#include <iostream>

using namespace std;

//在多态中,通常父类中的虚函数是毫无意义的,主要都是调用子类中重写的内容
//因此可以将虚函数改为纯虚函数
//当类中有了纯虚函数,这个类也称为抽象类 //抽象类特点:
//无法实例化对象
//子类必须重写抽象类中的纯虚函数,否则也属于抽象类 class Base
{
public:
//纯虚函数
virtual void func() = ;
}; class Son :public Base
{
public:
void func()
{
cout << "func()调用" << endl;
}
}; void test01()
{
Base* base = NULL;
//base = new Base;
base = new Son;
base->func();
delete base;
} int main()
{
test01(); system("pause"); return ;
}

纯虚函数和抽象类

#include <iostream>

using namespace std;

class zhiZuoYinPin
{
public:
virtual void shaoShui() = ;
virtual void chongPao() = ;
virtual void heTa() = ;
void liuCheng()
{
shaoShui();
chongPao();
heTa();
}
}; class Coffee :public zhiZuoYinPin
{
void shaoShui()
{
cout << "加热农夫山泉" << endl;
}
void chongPao()
{
cout << "冲泡咖啡" << endl;
}
void heTa()
{
cout << "喝咖啡" << endl;
}
}; class Tea :public zhiZuoYinPin
{
void shaoShui()
{
cout << "加热百岁山" << endl;
}
void chongPao()
{
cout << "冲泡龙井" << endl;
}
void heTa()
{
cout << "喝龙井" << endl;
}
}; void doWork(zhiZuoYinPin* zzyp)
{
zzyp->liuCheng();
delete zzyp;
} void test01()
{
doWork(new Coffee);
doWork(new Tea);
} int main()
{
test01(); system("pause"); return ;
}

多态制作饮品

#include <iostream>

using namespace std;

//使用多态时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构函数
//解决办法:将父类中的析构函数改为虚析构或纯虚析构 //虚析构和纯虚析构
//共性:
//可以解决父类指针释放子类对象
//都需要有具体的函数实现
//区别:
//如果是纯虚析构函数,该类属于抽象类,无法实例化
//如果子类中没有堆区数据,可以不写虚析构或纯虚析构 class Animal
{
public:
virtual void speak() = ; Animal()
{
cout << "Animal()构造函数调用" << endl;
} //虚析构函数
/*virtual ~Animal()
{
cout << "Animal()虚析构函数调用" << endl;
}*/ //纯虚析构函数
virtual ~Animal() = ;
}; Animal::~Animal()
{
cout << "Animal()纯虚析构函数调用" << endl;
} class Cat :public Animal
{
public:
string* m_name; public:
Cat(string name)
{
cout << "Cat构造函数调用" << endl;
m_name = new string(name);
} virtual ~Cat()
{
cout << "Cat析构函数调用" << endl;
if (this->m_name != NULL)
{
delete m_name;
m_name = NULL;
}
} void speak()
{
cout << *m_name << "小猫在说话" << endl;
}
}; void test01()
{
Animal* a = new Cat("Tom");
a->speak(); //通过父类指针去释放,会导致子类对象清理不干净,造成内存泄露
delete a; //给父类增加一个虚析构函数或纯虚析构函数
} int main()
{
test01(); system("pause"); return ;
}

虚析构函数和纯虚析构函数

#include <iostream>

using namespace std;

//C++中对文件操作需包含头文件<fstream>
#include <fstream> //文件类型分为两种:
//文本文件,以ASCII码形式存储
//二进制文件,以二进制形式存储 //操作文件的三大类:
//ofstream,写操作
//ifstream,读操作
//fstream,写读操作 //文本文件,写文件步骤:
//包含头文件
//创建流对象
//打开文件
//写数据
//关闭文件 //文件打开方式:
//ios::in 为读文件而打开文件
//ios::out 为写文件而打开文件
//ios::ate 初始位置:文件尾
//ios::app 追加方式写文件
//ios::trunc 如果文件存在先删除,在创建
//ios::binary 二进制方式 //文件打开方式可以配合 | 操作符使用
//如二进制方式写文件 ios::binary | ios::out void test01()
{
ofstream ofs;
ofs.open("test.txt", ios::out);
ofs << "姓名 = 张三" << endl;
ofs << "性别 = 男" << endl;
ofs.close();
} int main()
{
test01(); system("pause"); return ;
}

文本文件(写文件)

#include <iostream>

using namespace std;

#include <fstream>

//文本文件读文件步骤:
//包含头文件
//创建流对象
//打开文件并判断文件是否打开成功
//读数据
//关闭文件 void test01()
{
ifstream ifs;
ifs.open("test.txt", ios::in);
if (!ifs.is_open())
{
cout << "文件打开失败" << endl;
return;
} //
/*char buff[1024] = { 0 };
while (ifs >> buff)
{
cout << buff << endl;
}*/ //
/*char buff[1024] = { 0 };
while (ifs.getline(buff, sizeof(buff)))
{
cout << buff << endl;
}*/ //
char c;
while ((c = ifs.get()) != EOF)
{
cout << c;
} ifs.close();
} int main()
{
test01(); system("pause"); return ;
}

文本文件(读文件)

#include <iostream>

using namespace std;

#include <fstream>

//ostream& write(char* buffer , int len)
//buffer指向内存中一段存储空间,len是读写字节数 class Preson
{
public:
char m_name[];
int m_age;
}; void test01()
{
ofstream ofs("Preson.txt", ios::out | ios::binary); Preson p{ "李四", }; ofs.write((const char*)&p, sizeof(p)); ofs.close();
} int main()
{
test01(); system("pause"); return ;
}

二进制文件(写文件)

#include <iostream>

using namespace std;

#include <fstream>

//istream& read(char* buffer , int len)
//buffer指向内存中一段存储空间,len是读写字节数 class Preson
{
public:
char m_name[];
int m_age;
}; void test01()
{
ifstream ifs("Preson.txt", ios::in | ios::binary); if (!ifs.is_open())
{
cout << "文件打开失败" << endl;
return;
} Preson p; ifs.read((char*)&p, sizeof(p)); cout << "姓名 = " << p.m_name << endl;
cout << "年龄 = " << p.m_age << endl;
} int main()
{
test01(); system("pause"); return ;
}

二进制文件(读文件)

end

05-11 21:59