1、封装
1.1 属性和行为
cpp
#include <iostream>
using namespace std;
// 面向对象三大特性:封装、继承、多态
/*
封装的语法:
class 类名 {
访问权限:
属性(成员变量)
行为(成员函数)
};
*/
class Hero {
// 访问权限 public private protected
public:
// 属性
int m_Id; // m -> member
int m_Hp;
// 行为
void addHp(int hp) {
m_Hp += hp;
}
void subHp(int hp) {
m_Hp -= hp;
}
};
int main() {
// 通过类来生成对象的过程,叫 实例化
Hero h;
// 访问对象的属性
h.m_Id = 5;
h.m_Hp = 100;
h.addHp(100);
cout << "Id 为" << h.m_Id << "的英雄,血量是" << h.m_Hp << endl;
h.subHp(100);
cout << "Id 为" << h.m_Id << "的英雄,血量是" << h.m_Hp << endl;
return 0;
}
1.2 访问权限
cpp
#include <iostream>
using namespace std;
/*
访问权限
公共权限 public 类内可以访问,类外也可以访问
保护权限 protected 类内可以访问,类外不可以访问 子类可以访问
私有权限 private 类内可以访问,类外不可以访问 子类不可以访问(继承)
B -> A
A 父类、基类 名字、房子、支付密码
B 子类、派生类 公有、保护、私有
*/
class People {
// 公有权限
public:
int m_Id;
// 保护权限
protected:
int m_HouseId;
// 私有权限
private:
int m_PayPass;
public:
void work() {
// 所有成员变量,类内均可以访问
m_Id = 1;
m_HouseId = 2;
m_PayPass = 1314;
}
private:
void work1() {
// 所有成员变量,类内均可以访问
m_Id = 1;
m_HouseId = 2;
m_PayPass = 1314;
}
};
class Son : public People {
void func() {
m_Id = 1;
m_HouseId = 4; // 保护成员,子类可以访问
// m_PayPass = 123; // 私有成员,子类无法访问
People::work();
// People::work1();//私有成员,子类无法访问
}
};
int main() {
// 实例化
People p;
p.m_Id = 1; // 公有成员,类外可以访问
//p.m_HouseId = 5; // 保护成员,类外不可以访问
//p.m_PayPass = 10; // 私有成员,类外不可以访问
p.work();
// p.work1(); // 私有成员函数,类外不可访问
return 0;
}
1.3class和struct
cpp
#include <iostream>
using namespace std;
/*
struct && class
struct 默认是公共的
class 默认是私有的
*/
class C {
int m_a;
};
struct S {
int m_a;
void func() { //c和c++区别 c不能定义函数
m_a = 666;
}
};
int main() {
C c;
S s;
// c.m_a; // 私有的
s.m_a = 4; // 公有的
s.func();
cout << s.m_a << endl;//666
return 0;
}
1.4 属性私有化
cpp
#include <iostream>
#include <string>
using namespace std;
// 接口、方法、函数 是同一个概念
// 1、可以控制读写权限
// 2、可以检测数据的有效性
class Hero {
public:
//方法来访问属性成员变量
void SetName(string name) { //设置
m_Name = name;
}
string GetName() { //获取
return m_Name;
}
int GetSkillCount() {
return m_SkillCount;
}
void SetSpeed(int speed) { //设置
if (speed < 100 || speed > 500) {
cout << "速度设置不合法" << endl;
return;
}
m_Speed = speed;
}
private:
string m_Name; // 可读,可写
int m_SkillCount = 4; // 只读
int m_Speed; // 只写
};
int main() {
Hero h;
/* 不行,访问不了
h.m_Name = "123";
h.m_SkillCount = 4;
h.m_Speed = 10;
*/
h.SetName("剑圣");
cout << "英雄的名字叫:" << h.GetName() << endl;
cout << "英雄的技能数是:" << h.GetSkillCount() << endl;
h.SetSpeed(666);
return 0;
}
2、对象特性
2.1构造函数
cpp
#include <iostream>
#include <string>
using namespace std;
/*
构造函数需要注意的点
1、函数名称和类名保持一致
2、返回值类型 不需要写
3、构造函数可以有参数
*/
class Hero {
public:
// 默认构造函数
/* Hero() {
m_Name = "";
m_SkillCount = 4;
m_Speed = 100;
cout << "默认构造函数:Hero 构造完毕!" << endl;
}*/
// 有参构造函数1
Hero(string name="123") { //加了"123" Hero h1;也调用
m_Name = name;
m_SkillCount = 4;
m_Speed = 100;
cout << "有参构造函数1:Hero 构造完毕!" << endl;
}
// 有参构造函数2
Hero(string name , int skillCount) {
m_Name = name;
m_SkillCount = skillCount;
m_Speed = 100;
cout << "有参构造函数2:Hero 构造完毕!" << endl;
}
private:
string m_Name;
int m_SkillCount;
int m_Speed;
};
int main() {
Hero h1;
Hero h2("剑圣");
Hero h3(); // 函数声明 像int main(); int work(); 没调任何构造函数
Hero h4{};
Hero h5 = Hero("剑圣");
Hero h6{ "猴子", 4 };
return 0;
}
/*
默认构造函数:Hero 构造完毕!
有参构造函数1:Hero 构造完毕!
默认构造函数:Hero 构造完毕!
有参构造函数1:Hero 构造完毕!
有参构造函数2:Hero 构造完毕!
*/
2.2析构函数
cpp
#include <iostream>
using namespace std;
/*
析构函数注意点
1、函数名称和类名一致,并且在最前面加上一个 ~ 波浪号
2、函数返回值不需要写
3、不能有参数
*/
class Hero {
public:
// 构造函数 对象创建
Hero() {
cout << "Hero 默认构造函数调用完毕!" << endl;
}
// 析构函数 对象销毁
~Hero() {
cout << "Hero 析构函数调用完毕!" << endl;
}
};
void test() {
Hero h;
}
int main() {
test();
Hero h;
int a;
cin >> a;
return 0;
}
/*
Hero 默认构造函数调用完毕!
Hero 析构函数调用完毕!
Hero 默认构造函数调用完毕!
12
Hero 析构函数调用完毕!
*/
2.3拷贝构造函数
cpp
#include <iostream>
using namespace std;
/*
拷贝构造函数的定义
类名(const 类型& 变量名) {}
*/
class Hero {
public:
// 默认构造函数
Hero() {
m_Hp = 100;
cout << "Hero 默认构造函数调用完毕!" << endl;
}
// 有参构造函数
Hero(int hp) {
m_Hp = hp;
cout << "Hero 有参构造函数调用完毕!" << endl;
}
//拷贝构造函数
Hero(const Hero& h) {
// h.m_Hp = 4;//不可以
m_Hp = h.m_Hp;
cout << "Hero 拷贝构造函数调用完毕!" << endl;
}
// 析构函数
~Hero() {
cout << "Hero 析构函数调用完毕!" << endl;
}
private:
int m_Hp;
};
/*
拷贝构造函数的调用时机
1、用已经创建的对象来初始化对象
2、函数的传参
3、函数的返回值
*/
// 1、用已经创建的对象来初始化对象
void func1() {
cout << "--------------func1--------------" << endl;
Hero h1(20);
Hero h2(h1);
}
// 2
void test1(Hero h) {
}
void test2(Hero* h) {
}
// 2、函数的传参
void func2() {
cout << "--------------func2--------------" << endl;
Hero h1;
// test1(h1);//调拷贝
test2(&h1);//传指针,没有生成对象,不调用拷贝
}
// 3、函数的返回值
Hero test3() {
Hero h(40);
return h;
}
void func3() {
cout << "--------------func3--------------" << endl;
Hero h = test3(); //会优化,不调用拷贝构造函数,
//解决:右键点击属性->c/c++->命令行 /Zc:nrvo-
}
int main() {
func1();
func2();
func3();
return 0;
}
2.4初始化列表
cpp
#include <iostream>
#include <string>
using namespace std;
/*
初始化列表的语法
构造函数(传参1, 传参2): 成员变量1(传参1), 成员变量2(传参2) {}
*/
class Hero {
public:
/*Hero(string name, int hp) {
m_Name = name;
m_Hp = hp;
}*/
Hero(string name, int hp, int speed) : m_Name(name), m_Hp(hp), m_Speed(speed) {
}
void Print() {
cout << "英雄:" << m_Name << "的血量是" << m_Hp << ",速度是" << m_Speed << endl;
}
private:
string m_Name;
int m_Hp;
int m_Speed;
};
int main() {
Hero h("剑圣", 100, 10);
h.Print();
return 0;
}
2.5静态成员变量
cpp
#include <iostream>
#include <string>
using namespace std;
/*
静态成员变量的特点:
1、所有的对象共享同一份数据
2、编译阶段分配内存
3、需要在类中进行声明,在类外进行初始化
*/
class Hero {
public:
Hero() {
m_Name = "英雄";
m_Hp = 100;
}
~Hero() {
}
// 3.1 声明
static int m_HeroCount;
private:
string m_Name;
int m_Hp;
};
// 3.2 初始化
int Hero::m_HeroCount = 100;//作用域 Hero::
int main() {
Hero h;
cout << h.m_HeroCount << endl;//1 100
h.m_HeroCount = 101;
cout << Hero::m_HeroCount << endl;//2 101
cout << &(h.m_HeroCount) << endl;//00007FF6BC742000
cout << &(Hero::m_HeroCount) << endl;//00007FF6BC742000 同一个变量
return 0;
}
2.6静态成员函数
cpp
#include <iostream>
#include <string>
using namespace std;
/*
静态成员函数
1、所有对象共享函数
2、静态成员函数只能使用静态成员变量,无法使用普通成员变量
*/
class Hero {
public:
Hero() {
m_Name = "英雄";
m_Hp = 100;
}
~Hero() {
}
static int m_HeroCount;
static int GetHeroCount() { //静态成员函数
//m_Hp += 1;
return m_HeroCount;
}
private:
string m_Name;
int m_Hp;
static int GetHeroCount1() {
// m_Hp += 1;
return m_HeroCount;
}
};
int Hero::m_HeroCount = 100;
int main() {
Hero h;
cout << h.GetHeroCount() << endl;
cout << Hero::GetHeroCount() << endl;
//h.GetHeroCount1();//拿不了
return 0;
}
2.7 this指针
cpp
#include <iostream>
using namespace std;
/*
this指针
1、解决命名冲突
2、*this 就可以获取到这个对象本身
this *this
&h *(&h) == h
*/
class Hero {
public:
Hero(int hp) {
//hp = hp;//形参覆盖实参
this->hp = hp;
cout << this << endl;//地址 000000BFDDF1F984
cout << (*this).hp << endl;//100
}
int hp;
};
int main() {
Hero h(100);
cout << h.hp << endl;//100
cout << &h << endl; //000000BFDDF1F984 一样
cout << (*(&h)).hp << endl;//100
return 0;
}
2.8 const修饰成员函数
cpp
#include <iostream>
#include <vector>
using namespace std;
// 常函数
class Hero {
public:
Hero() : m_Hp(0) {}
int getHp() const {
// m_Hp = m_Hp + 1;//无法修改成员变量的值
return m_Hp;
}
int setHp(int hp) {
m_Hp = hp;
}
private:
int m_Hp;
};
int main() {
const Hero h;//不能被修改
// h.setHp(100);//常量不能调用非常量函数
h.getHp();
return 0;
}
2.9 mutable关键字
cpp
#include <iostream>
using namespace std;
// mutable 可变 <-> const
class Hero {
public:
Hero() :m_Hp(0), m_getHpCounter(0) {}
int getHp() const {
m_getHpCounter++;
return m_Hp;
}
void printCounter() const {
cout << "Counter: " << m_getHpCounter << endl;
}
private:
int m_Hp;
mutable int m_getHpCounter;//const函数里可操作
};
int main() {
Hero h;
h.getHp(), h.getHp(), h.getHp(), h.getHp(), h.getHp(), h.getHp();//调6次
h.printCounter();
return 0;
}
3、友元
3.1全局函数作为友元
cpp
#include <iostream>
#include <string>
using namespace std;
/*
友元的目的
让一个类 或者 函数
能够访问另一个类的私有成员
友元的关键字: friend
三种友元
1、全局函数作为友元
2、类作为友元
3、成员函数作为友元
*/
class People {
friend void friendVisit(People* p);
public:
People() {
m_House = "别墅";
m_Car = "跑车";
}
public:
string m_House;
private:
string m_Car;
};
void friendVisit(People* p) {
cout << "好朋友来访问你的" << p->m_House << endl;
cout << "好朋友来访问你的" << p->m_Car << endl;//私有成员访问
}
int main() {
People p;
friendVisit(&p);
return 0;
}
3.2类作为友元
cpp
#include <iostream>
using namespace std;
// 类作为友元
// 让一个类去访问另一个类的私有成员
class People;//声明
class PeopleFriend {
public:
PeopleFriend() {
}
void visit(People* p);
/*void visit(People* p) {
cout << "好朋友来访问你的" << p->m_House << endl;
cout << "好朋友来访问你的" << p->m_Car << endl;//m_House,m_Car 还没执行到,不知道,放在后面实现
}*/
};
class People {
friend class PeopleFriend;//访问私有
public:
People() {
m_House = "别墅";
m_Car = "跑车";
}
public:
string m_House;
private:
string m_Car;
};
//函数实现
void PeopleFriend::visit(People* p) {
cout << "好朋友来访问你的" << p->m_House << endl;
cout << "好朋友来访问你的" << p->m_Car << endl;
}
int main() {
People p;
PeopleFriend pf;
pf.visit(&p);
return 0;
}
3.3成员函数作为友元
cpp
#include <iostream>
#include <string>
using namespace std;
// 成员函数作为友元
// PeopleFriend 的某个函数能够访问 People 的私有成员变量
class People;
class PeopleFriend {
public:
PeopleFriend() {}
void visitAll(People* p);
void visitPub(People* p);
};
class People {
// friend class PeopleFriend;
friend void PeopleFriend::visitAll(People* p);
public:
People() {
m_House = "别墅";
m_Car = "跑车";
}
public:
string m_House;
private:
string m_Car;
};
void PeopleFriend::visitAll(People* p) {
cout << "好朋友访问了你的" << p->m_House << endl;
cout << "好朋友访问了你的" << p->m_Car << endl;
}
void PeopleFriend::visitPub(People* p) {
cout << "好朋友访问了你的" << p->m_House << endl;
//cout << "好朋友访问了你的" << p->m_Car << endl;//不可访问
}
int main() {
People p;
PeopleFriend pf;
pf.visitAll(&p);
pf.visitPub(&p);
return 0;
}
4、运算符重载
4.1概念
参考网址:C++语法------详解运算符重载_c++运算符重载-CSDN博客
cpp
#include <iostream>
#include <string> //是一个类
using namespace std;
/*
+
4 + 5 = 9
class A {
};
A a;
A b;
a + b;
*/
int main() {
// 1、加法运算符
int a = 520;
int b = 1314;
cout << a + b << endl;
// 2、字符串拼接
string c = "520";
string d = "1314";
cout << c + d << endl;//5201314 运算符重载
string e = "我";
string f = "爱你";
cout << e + f << endl;
return 0;
}
4.2 +号重载
重载形式:[返回值] operator[运算符] (参数...) { ... };
cpp
#include <iostream>
using namespace std;
/*
+
*/
// 复数类
class Complex {
friend Complex operator+(Complex& a, Complex& b);
friend Complex operator-(Complex& a, Complex& b);
public:
Complex() : real(0), image(0) {
}
Complex(int real, int image) {
this->real = real;
this->image = image;
}
//复数相加函数
Complex add(Complex& other) {
Complex ret;
ret.real = this->real + other.real;//this 是 指针 other 是 对象
ret.image = this->image + other.image;
return ret;
}
成员函数重载
//Complex operator+(Complex& other) {
// Complex ret;
// ret.real = this->real + other.real;
// ret.image = this->image + other.image;
// return ret;
//}
// a + bi
void Print() {
cout << real << '+' << image << 'i' << endl;
}
private:
int real;//实部
int image;//虚部
};
//全局函数重载实现 需要两个对象
Complex operator+(Complex& a, Complex& b) { //引入友元
Complex ret;
ret.real = a.real + b.real;
ret.image = a.image + b.image;
return ret;
}
Complex operator-(Complex& a, Complex& b) {
Complex ret;
ret.real = a.real - b.real;
ret.image = a.image - b.image;
return ret;
}
int main() {
Complex a(10, 20);
Complex b(5, 8);
Complex c =a.add(b);
c.Print();//15+28i
//Complex c = a.operator+(b);//15+28i
//Complex c1 = a + b;//函数名变成operator+实现 可以直接实现 成员函数
//全局函数
Complex c1 = a + b;
Complex d = a - b;
c1.Print();
d.Print();//5+12i
return 0;
}
4.3 左移重载
cpp
#include <iostream>
using namespace std;
/*
左移运算符 :<< 把对象输出来
Complex c;
cout.operator<<(c) 实现
// 成员函数重载
c.operator<<(cout) cout是ostream对象
c << cout 这个不是我们想实现的
*/
// 复数类
class Complex {
friend Complex operator+(Complex& a, Complex& b);
friend Complex operator-(Complex& a, Complex& b);
friend ostream& operator<<(ostream& cout, Complex a);
public:
Complex() : real(0), image(0) {
}
Complex(int real, int image) {
this->real = real;
this->image = image;
}
/*
Complex operator+(Complex& other) {
Complex ret;
ret.real = this->real + other.real;
ret.image = this->image + other.image;
return ret;
}*/
// a + bi
void Print() {
cout << real << '+' << image << 'i' << endl;
}
private:
int real;
int image;
};
Complex operator+(Complex& a, Complex& b) {
Complex ret;
ret.real = a.real + b.real;
ret.image = a.image + b.image;
return ret;
}
Complex operator-(Complex& a, Complex& b) {
Complex ret;
ret.real = a.real - b.real;
ret.image = a.image - b.image;
return ret;
}
//cout重载实现
ostream& operator<<(ostream& cout, Complex a) {//&不会调到拷贝构造函数 只有一个cout
cout << a.real << '+' << a.image << 'i';
return cout;//要有返回值<< endl才能实现
}
int main() {
Complex a(10, 20);
Complex b(5, 8);
// Complex c = a.operator+(b);
Complex c = a + b;
Complex d = a - b;
//c.Print();
//d.Print();
// operator<<(cout, c)
cout << c << endl << endl;//重载来实现Complex c的输出
return 0;
}

有delete 任何地方的不能调用cout的拷贝构造函数。
4.4 递增重载
cpp
#include <iostream>
using namespace std;
/*
++
前置 ++
后置 ++
*/
class Complex {
friend ostream& operator<<(ostream& c, const Complex& a);
public:
Complex() : real(0), image(0) {}
Complex(int real, int image) { //有参构造函数
this->real = real;
this->image = image;
}
Complex& operator++() { //前置 ++
this->real += 1;
return *this; //返回Complex&,就可以用cout << ++(++a) << endl;
}
Complex operator++(int) { //后置++ 加一个占位符 且必须是int 类型
Complex c = *this; //要返回另一个对象
this->real += 1;
return c;
}
private:
int real;
int image;
};
//复数的输出
ostream& operator<<(ostream& c, const Complex& a) { //c is cout
c << a.real << '+' << a.image << 'i';
return c;
}
class A {
};
A func1() { // 模拟Complex operator++(int)
return A();
}
void func2(const A& a) { //模拟ostream& operator<<(ostream& c, const Complex& a)
}
int main() {
int x = 1;
cout << ++(++x) << endl;//3
cout << x << endl;//3
Complex a(10, 10);
cout << a << endl;//10+10i
// ++a;
cout << ++(++a) << endl;//12+10i
// cout << a << endl;//11+10i 不加引用时 前置生成另一个对象
cout << a << endl;//12+10i 加引用时
cout << a++ << endl;//12+10i
cout << a << endl;//13+10i
//func2(func1());//不加const错误 非常量引用的初始值必须为左值
// cout << ((a++)++)++ << endl;不可以这样写
cout << a << endl;//13+10i
int b = 5;
// cout << ((b++)++)++ << endl;不可以这样写
cout << b << endl;
return 0;
}
4,5 赋值重载
cpp
#include <iostream>
using namespace std;
class Hero {
public:
Hero() : m_Data(NULL) {}
Hero(int data) {
m_Data = new int;//内存申请
*m_Data = data;
}
// 错误:double delete
~Hero() {
if (m_Data) {//感受内存泄露 if 不重载赋值号:会报错
delete m_Data;//一个内存调用两次delete 不行
m_Data = NULL;
}
}
//解决
Hero& operator=(Hero& h) {
// m_Data = h.m_Data;//double free问题
if (m_Data) {
delete m_Data;
m_Data = NULL;
}
// m_Data=NULL执行
m_Data = new int;
*m_Data = *h.m_Data;
return *this; //h3 = (h2 = h1);实现
}
int* m_Data;
};
int main() {
Hero h1(1);
Hero h2(2);
// if 不重载赋值号
// h1 = h2;//h2的m_Data会覆盖h1的m_Data ,内存相同 ,内存泄露
Hero h3(3);
cout << h1.m_Data << endl;
cout << h2.m_Data << endl;
h1 = h2; //
cout << h1.m_Data << endl;
cout << h2.m_Data << endl;
h3 = (h2 = h1);
cout << h1.m_Data << endl;
cout << h2.m_Data << endl;
cout << h3.m_Data << endl;
return 0;
}
4.6 关系运算符重载
cpp
#include <iostream>
using namespace std;
class Point { //点类
public:
Point(int x, int y) : m_x(x), m_y(y) {
}
bool operator==(const Point& other) const {//函数const包含m_x 和 m_y
return m_x == other.m_x && m_y == other.m_y;
}
bool operator<(const Point& other) const {
int d = m_x * m_x + m_y * m_y;
int otherd = other.m_x * other.m_x + other.m_y * other.m_y;
return d < otherd;
}
bool operator>(const Point& other) const {
if (*this == other) {
return false;
}
if (*this < other) {
return false;
}
return true;
}
private:
int m_x, m_y;
};
int main() {
Point a(1, 6);
Point b(2, 5);
if (a == b) { //一个类==要重载
cout << "a 和 b 相等" << endl;
}
else if (a < b) {
cout << "a 比 b 更加接近原点" << endl;
}
else if (a > b) {
cout << "b 比 a 更加接近原点" << endl;//b 比 a 更加接近原点
}
return 0;
}
4.7 函数调用运算符重载
cpp
#include <iostream>
using namespace std;
// ()
// add()
class AddFunctor {
public:
AddFunctor() {
m_acc = 0;
}
int operator() (int a, int b) {
m_acc++;
return a + b + m_acc;
}
private:
int m_acc;
};
int Add(int a, int b) {
return a + b;
}
int main() {
AddFunctor add;//对象
cout << add(5, 6) << endl;//仿函数
cout << add(5, 6) << endl;
cout << add(5, 6) << endl;
cout << add(5, 6) << endl;
cout << add(5, 6) << endl;
cout << Add(5, 6) << endl;//每次调用一样
cout << Add(5, 6) << endl;
cout << Add(5, 6) << endl;
cout << Add(5, 6) << endl;
cout << Add(5, 6) << endl;
//12 13 14 15 16 11 11 11 11 11
return 0;
}
5、继承
5.1 继承的语法
cpp
#include <iostream>
using namespace std;
/*
* 动物
* / \
* 猫 狗
*
* 继承的语法
* class 子类 : 继承方式 父类 {}
* 子类 -> 派生类
* 父类 -> 基类
*/
class Animal {
public:
void eat() {
cout << "吃" << endl; //猫,狗都吃,所以抽象在一个类
}
};
class Cat : public Animal {
public:
void sayHi() {
cout << "喵~" << endl;
}
};
class Dog : public Animal {
public:
void sayHi() {
cout << "汪汪汪~" << endl;
}
};
int main() {
Cat c;
Dog d;
c.eat();
d.eat();
c.sayHi();
d.sayHi();
return 0;
}
5.2 继承的方式
cpp
#include <iostream>
using namespace std;
/*
继承方式
class 子类名 : 继承方式 父类名 {};
公共 public
保护 protected
私有 private
3 x 3 = 9
父类权限
| public | protected | private
子类继承方式
public | public | protected | 无法访问
protected | protected | protected | 无法访问
private | private | private | 无法访问
public: 类内可以访问,类外也可以访问
protected: 类内可以访问,类外不可访问,且子类可以访问
private: 类内可以访问,类外不可访问,且子类不可访问
*/
class Animal {
public:
int m_pub;
protected:
int m_pro;
private:
int m_pri;
};
class Cat : public Animal {
public:
Cat() {
m_pub = 1;
m_pro = 2;
// m_pri = 3; 父类私有成员,子类公有继承,无法访问
}
};
class BossCat : public Cat {
public:
BossCat() {
m_pub = 1;
m_pro = 2; // 父类Cat中不是私有
}
};
void testCat() {
Cat c;
c.m_pub = 1;
// c.m_pro = 2; // 要么是私有,要么是保护
}
//2
class Dog : protected Animal {
public:
Dog() {
m_pub = 1;
m_pro = 2;
// m_pri = 3; // 父类私有成员,子类保护继承,无法访问
}
};
class PoliceDog : public Dog {
public:
PoliceDog() {
m_pub = 1; // 这个变量,在父类 Dog 中一定不是私有成员
m_pro = 2; // 这个变量,在父类 Dog 中一定不是私有成员
}
};
void testDog() {
Dog d;
// d.m_pub = 1; // 要么是保护,要么是私有
// d.m_pro = 2; // 要么是保护,要么是私有
}
//3
class Pig : private Animal {
public:
Pig() {
m_pub = 1;
m_pro = 2;
// m_pri = 3; // 父类私有成员,子类私有继承,无法访问
}
};
class WildPig : public Pig {
public:
WildPig() {
// m_pub = 1; // 该变量在父类 Pig 中是私有的
// m_pro = 2; // 该变量在父类 Pig 中是私有的
}
};
void testPig() {
Pig p;
// p.m_pub = 1; // 要么是保护,要么是私有
// p.m_pro = 2; // 要么是保护,要么是私有
}
int main() {
return 0;
}
5.3 构造函数和析构函数顺序
cpp
#include <iostream>
using namespace std;
/*
继承中,构造链里,先构造的后析构
d -> c -> b -> a d继承a..
a b c d d c b a
*/
class Animal {
public:
Animal() {
cout << "Animal 构造" << endl;
}
~Animal() {
cout << "Animal 析构" << endl;
}
};
class Cat : public Animal {
public:
Cat() {
cout << "Cat 构造" << endl;
}
~Cat() {
cout << "Cat 析构" << endl;
}
};
class BossCat : public Cat {
public:
BossCat() {
cout << "BossCat 构造" << endl;
}
~BossCat() {
cout << "BossCat 析构" << endl;
}
};
void Test() {
//Animal a;
//Cat c;//先调父类的构造,再调自己
BossCat b;
}
int main() {
Test();
return 0;
}
5.4 同名属性的访问
cpp
#include <iostream>
using namespace std;
//父类和子类变量名相同
class Animal {
public:
Animal() {
m_Data = 17891;
}
int m_Data;
};
class Cat : public Animal {
public:
Cat() {
m_Data = 29812;
}
int m_Data;
};
void Test() {
Cat c;
cout << c.m_Data << endl;//29812
cout << c.Animal::m_Data << endl;//17891
cout << &(c.m_Data) << endl;//0000003C3011F92C
cout << &(c.Animal::m_Data) << endl;//0000003C3011F928 不会覆盖
}
int main() {
Test();
return 0;
}
5.5 同名函数访问
cpp
#include <iostream>
using namespace std;
class Animal {
public:
Animal() {
}
void eat() {
cout << "动物吃东西" << endl;
}
};
class Cat : public Animal {
public:
Cat() {
}
void eat() {
// Animal::eat();//第一种
cout << "猫吃东西" << endl;
}
};
int main() {
Cat c;
c.eat();//子类覆盖父类
//c.Animal::eat();//第二种
return 0;
}
5.6 多继承
cpp
#include <iostream>
using namespace std;
class BaseA {
public:
int m_A;
int m_Base;
BaseA() : m_A(0), m_Base(520) {}//初始化
};
class BaseB {
public:
int m_B;
int m_Base;
BaseB() : m_B(0), m_Base(1314) {}
};
class BaseC {
public:
int m_C;
BaseC() : m_C(0) {}
};
class Son : public BaseA, public BaseB, public BaseC {
};
int main() {
Son s;
s.m_A = 1;
s.m_B = 2;
s.m_C = 3;
//s.m_Base = 8;//错误:不明确
s.BaseA::m_Base = 8;
s.BaseB::m_Base = 9;
cout << &s.BaseA::m_Base << endl;//存在不同地址
cout << &s.BaseB::m_Base << endl;
cout << sizeof(s) << endl;//20 5个整型
return 0;
}
6、多态
6.1 多态的语法
cpp
#include <iostream>
using namespace std;
/*
静态多态:函数重载,运算符重载
动态多态:派生类和虚函数实现运行时的多态
*/
class Animal {
public:
// 虚函数
virtual void eat() {
cout << "动物在吃东西" << endl;
}
};
class Cat : public Animal {
public:
void eat() {
cout << "猫在吃东西" << endl;
}
};
class Pig : public Animal {
public:
void eat() {
cout << "猪在吃东西" << endl;
}
};
// main -> test -> eat -> Animal::eat
// 函数传参是个动物,但是传入不同的动物,会产生不同的行为,这就叫多态
void eat(Animal& a) {
a.eat();
}
void Test() {
Cat c;
Pig p;
eat(c);//不加virtual,调用Animal的eat()
eat(p);//加了 eat()猪在吃东西
}
int main() {
Test();
return 0;
}
6.2 虚函数
cpp
#include <iostream>
using namespace std;
class Animal {
public:
virtual void eat() {
cout << "动物在吃东西" << endl;
}
virtual void run() {
cout << "动物在跑" << endl;
}
};
class Cat : public Animal {
public:
void eat() {
cout << "猫在吃东西" << endl;
}
};
void eat(Animal& a) {
Animal b;
a.eat();
}
void Test() {
Cat c;
eat(c);
cout << "Animal's size = " << sizeof(Animal) << endl;//不加virtual =1 加了=8->指针大小
}
int main() {
Test();
return 0;
}
6.3 纯虚函数和抽象类
cpp
#include <iostream>
using namespace std;
class Animal { //有纯虚函数 是抽象类 无法实例化
public:
virtual void eat() = 0;//纯虚函数,在子类实现
};
class Cat : public Animal {
public:
virtual void eat() {
cout << "猫在吃东西" << endl;
}
};
int main() {
Cat c;
c.eat();
return 0;
}
6.4 虚析构和纯虚析构
cpp
#include <iostream>
using namespace std;
class BaseA {
public:
BaseA() {}
~BaseA() {
cout << "BaseA 销毁了" << endl;
}
};
class SonA : public BaseA {
public:
SonA() : m_Value(NULL) {
m_Value = new int(10);//初始化 为10
}
~SonA() {
cout << "SonA 销毁了" << endl;
delete m_Value;
}
int* m_Value;
};
class BaseB {
public:
BaseB() {}
/*virtual ~BaseB() {
cout << "BaseB 销毁了" << endl;
}*/
virtual ~BaseB() = 0;//纯虚析构
};
BaseB::~BaseB() {
cout << "BaseB 销毁了" << endl;
}
class SonB : public BaseB {
public:
SonB() : m_Value(NULL) {
m_Value = new int(10);
}
~SonB() {
cout << "SonB 销毁了" << endl;
delete m_Value;
}
int* m_Value;
};
int main() {
BaseA* a = new SonA();
delete a;
BaseB* b = new SonB();
delete b;
// BaseB x; 抽象类无法进行实例化
return 0;
}