封装

面向对象三大特性:封装、继承、多态

封装

属性、行为、实例化

一个类里封装了它的属性(成员变量)、行为(成员函数),通过public、private、protected来控制访问权限。

在需要对象时,通过实例化(通过类来生成对象的过程)来生成对象。

/*
封装的语法

class 类名{
访问权限:
	属性(成员变量)
	行为(成员函数)
}
*/
class People{
// 访问权限  public、private、protected
public:
    //属性
    int m_Id;			//m -> member
    int m_Age;
    //行为
	void fun(int id){
        m_Id = id;
    }
}

int main(){
    //通过类来生成对象的过程,叫  实例化
    People p;
    //访问对象的属性
    p.m_Id = 1;
    p.fun(2);
    return =;
}

访问权限

公共权限 public 类内可以访问,类外也可以访

保护权限 protected 类内可以访问,类外不可以访问 子类可以访问

私有权限 private 类内可以访问,类外不可以访问 子类不可以访问

#include<iostream>
using namespace std;

class People {
	//公有权限
public:
	int m_Id;
	//保护权限
protected:
	int m_HouseId;
	//私有权限
private:
	int m_PayPass;

public://
	void work() {
		//所有成员变量,类内均可访问
		m_Id = 1;
		m_HouseId = 12138;
		m_PayPass = 000000;
	}
private:
	void fun() {
		m_Id = 1;
		m_HouseId = 12138;
		m_PayPass = 000000;
	}
};

class Son : public People {
	void fun() {
		m_Id = 2;
		m_HouseId = 3;		//保护成员,子类可以访问
		m_PayPass = 111;	//私有成员,子类无法访问
	}
};

int main() {
	//实例化
	People p;
	p.m_Id = 1;				//公共成员,类外可以访问
	p.m_HouseId = 5;		//保护成员,类外不可访问
	p.m_PayPass = 1111;		//私有成员,类外不可访问

	p.work();
	p.fun();				//私有成员函数,类外不可访问

	return 0;
}

class和struct的区别

C++中,class和struct只有访问权限的区别

struct 默认是公共的 (C++中可以定义成员函数,C中不可以)

class 默认是私有的

#include<iostream>
using namespace std;

class C {
	int m_a;
};

struct S {
	int m_a;
	
	void fun() {
		m_a = 666;
	}
};

int main() {
	C c;
	S s;

	c.m_a = 4;			//私有的,访问不到
	s.m_a = 5;			//公有的,能访问
	s.fun();			//struct可以定义成员函数

	return 0;
}

属性私有化

把成员属性私有化,提供公有方法来对数据进行访问

  1. 可以控制读写权限(提供Get、Set方法)
  2. 可以检测数据的有效性(在Set方法中判断数据有效性)
#include<iostream>
using namespace std;

//接口、方法、函数 是一个概念

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.SetName("无极剑圣");
	cout << h.GetName() << endl;
	cout << h.GetSkillCount() << endl;
	h.SetSpeed(666);
	
}

对象特性

构造函数

构造函数由程序员实现、由编译器调用。(若程序员没有主动实现构造函数,编译器提供一个默认构造函数,里面没有任何实现)

class People{
public:
	//构造函数
	People(){
        初始化成员变量
	}
    
    int 成员变量;
    string 成员变量;
}

注意:

  1. 函数名称与类名保持一致
  2. 返回值类型 不需要写
  3. 构造函数可以有参数
#include<iostream>
#include<string>
using namespace std;

//构造函数需要注意的点
/*
* 1、函数名称与类名保持一致
* 2、返回值类型 不需要写
* 3、构造函数可以有参数
*/
class Hero {
public:
	//构造函数
	//默认(无参)构造函数
	Hero() {
		m_Name = "";
		m_SkillCount = 4;
		m_Speed = 200;
		cout << " 默认构造函数:hero 构造完毕" << endl;
	}
	//有参构造函数(可以有多个)
    //有参构造函数1
	Hero(string name) {
		m_Name = name;
		m_SkillCount = 4;
		m_Speed = 200;
		cout << " 有参构造函数1:hero 构造完毕"<< m_Name << endl;
	}
    //有参构造函数2
    Hero(string name, int skillCount) {
		m_Name = name;
		m_SkillCount = skillCount;
		m_Speed = 200;
		cout << " 有参构造函数2:hero 构造完毕"<< m_Name << endl;
	}

private:
	string m_Name;			
	int m_SkillCount = 4;		
	int m_Speed;			
};

int main() {
	Hero h1;
	Hero h2("无极剑圣");
	Hero h3(); // 这其实是函数声明   int main(); 、 int work();  类型 函数名();
	Hero h4{}; //默认(无参)
	Hero h5 = Hero("齐天大圣");
}

析构函数

析构函数给对象进行反初始化(数据清洗),在对象销毁前,由系统自动调用。(若程序员没有主动实现,编译器提供一个默认析构函数,里面没有任何实现)

class People{
public:
	//构造函数
	People(){
        初始化成员变量
	}
    //析构函数
    ~People(){
		反初始化成员变量
    }
    
    int 成员变量;
    string 成员变量;
}

注意:

  1. 函数名称和类名一致,并且在最前面加上一个~ 波浪号
  2. 函数返回值不需要写
  3. 不能有参数
class Hero {
public:
	//构造函数
	Hero() {
		cout << " 默认构造函数调用完毕" << endl;
	}
	//析构函数
	~Hero() {
		cout << " 析构函数调用完毕" << endl;
	}
	

private:
	string m_Name;			
	int m_SkillCount = 4;		
	int m_Speed;			
};



int main() {
	Hero h;
}

拷贝构造函数

调用别的对象的数据来生成新的对象(使用常量引用防止调用的对象内容被修改)

拷贝构造函数定义:类名(const 类型& 变量名){}

class People{
public:
	//构造函数
	People(){
        初始化成员变量
	}
    //拷贝构造函数
    // 调用别的对象的数据来生成新的对象
    //(const People& h) 常量引用
    //  使用引用传入别名,避免拷贝开销
    //  使用常量防止h的成员变量被修改
    People(const People& h){
        成员变量 = h.成员变量;
    }
    
    //析构函数
    ~People(){
		反初始化成员变量
    }
    
    int 成员变量;
    string 成员变量;
}
  1. 用已经创建的对象来初始化对象

    void func1() {
    	cout << "-------------func1-------------" << endl;
    	Hero h1("20");
    	Hero h2(h1);
    }
    

  1. 函数的传参

    void test1(Hero h) {
    
    }
    
    void test2(Hero* h) {
    
    }
    
    void func2() {
    	cout << "-------------func2-------------" << endl;
    	Hero h1;
    	test1(h1);
    	//test2(&h1);//传入指针,没有生成新的对象,不会调用构造函数
    }
    

  2. 函数的返回值

    Hero test3() {
    	Hero h("40");
    	return h;
    }
    
    void func3() {
    	cout << "-------------func3-------------" << endl;
    	Hero h = test3();
    }
    
#include<iostream>
#include<string>
using namespace std;

class Hero {
public:
	//默认构造函数
	Hero() {
		m_Name = "大圣";
		cout << " 默认构造函数调用完毕" << endl;
	}

	//有参构造函数
	Hero(string name) {
		m_Name = name;
		cout << " 有参构造函数调用完毕" << endl;
	}

	//拷贝构造函数
	Hero(const Hero& h) {
		m_Name = h.m_Name;
		cout << " 拷贝构造函数调用完毕" << endl;
	}

	//析构函数
	~Hero() {
		cout << " 析构函数调用完毕" << endl;
	}
	

private:
	string m_Name;						
};

void func1() {
	cout << "-------------func1-------------" << endl;
	Hero h1("20");
	Hero h2(h1);
}

void test1(Hero h) {

}

void test2(Hero* h) {

}

void func2() {
	cout << "-------------func2-------------" << endl;
	Hero h1;
	test1(h1);
	test2(&h1);//传入指针,没有生成新的对象,不会调用构造函数
}

Hero test3() {
	Hero h("40");
	return h;
}

void func3() {
	cout << "-------------func3-------------" << endl;
	Hero h = test3();
}

int main() {
	func1();
	func2();
	func3();
	return 0;
}

初始化列表

初始化列表的语法:构造函数(传参1,传参2): 成员变量1(传参1),成员变量2(传参2){}

#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) :m_Name(name), m_Hp(hp) {
	}

	void Print() {
		cout << "英雄:" << m_Name << "的血量是:" << m_Hp << endl;
	}
	
private:
	string m_Name;
	int m_Hp;
};

int main() {
	Hero h1("无极剑圣", 100);
	h1.Print();
	return 0;
}

静态成员变量

特点:

  1. 所有对象共享同一份数据
  2. 编译阶段分配内存
  3. 需要在类内进行声明,在类外进行初始化
#include<iostream>
#include<string>
using namespace std;

class Hero {
public:

	Hero() {
		m_Name = "剑圣";
		m_Hp = 100;
	}
	~Hero() {

	}
	//1.声明
	static int m_HeroCount;//静态成员变量

private:
	string m_Name;
	int m_Hp;
};

//2.初始化
int Hero::m_HeroCount = 100;//不初始化就会link错误

int main() {
	Hero h1;
	cout << h1.m_HeroCount << endl;
	cout << Hero::m_HeroCount << endl;
	cout << &(h1.m_HeroCount) << endl;
	cout << &(Hero::m_HeroCount) << endl;

	return 0;
}

静态成员函数

特点:

  1. 所有对象共享函数
  2. 静态成员函数内部只能用静态成员变量
#include<iostream>
#include<string>
using namespace std;

class Hero {
public:

	Hero() {
		m_Name = "剑圣";
		m_Hp = 100;
	}
	~Hero() {

	}
	static int m_HeroCount;

	static int GetHeroCount() {
		return m_HeroCount;
	}

private:
	string m_Name;
	int m_Hp;
};

int Hero::m_HeroCount = 100;

int main() {
	Hero h1;
	cout << h1.GetHeroCount << endl;
	cout << Hero::GetHeroCount << endl;

	return 0;
}

this指针

作用:

  1. 解决命名冲突
  2. *this 就可以获取到这个对象本身

this代表这个对象的地址

this *this
&h *(&h)==h
class Hero {
public:
	Hero(int hp) {
		this->hp = hp;
        //*(this).hp = hp; 作用同上
		cout << this << endl;
	}
	int hp;
};

int main() {
	Hero h(100);
	cout << h.hp << endl;
	cout << &h << endl;
	return 0;
}

const修饰成员函数

常函数:常量对象只能调用常函数

#include<iostream>
#include<string>
using namespace std;

//常函数
class Hero {
public:
	Hero(int hp) {
		this->hp = hp;
		cout << this << endl;
	}
	int GetHp() const {//常函数不能修改成员变量的值
		//hp += hp;//错误,hp不能修改
		return hp;
	}
    int SetHp(int hp){
        this->hp = hp;
    }
private:
	int hp;
};

int main() {
	const Hero h;//常量h  常量对象只能调用常函数
    //h.SetHp(100);//无法修改h里的值
    h.Gethp();//可以获得h里的值
}

mutable关键字

mutable <-> const

为了让常函数使用修改成员变量,给成员变量加上mutable关键字

#include<iostream>
#include<string>
using namespace std;

class Hero {
private:
	int m_Hp;
	mutable int m_getHpCounter;//加上mutable关键字
public:
	Hero() :m_Hp(2), m_getHpCounter(0){
	}
	int getHp() const {//常函数中就能使用m_getHpCounter了
		m_getHpCounter++;
		return m_Hp;
	}
	void printCounter() const {//常函数中就能使用m_getHpCounter了
		cout << m_getHpCounter << endl;
	}

};

int main() {
	Hero h;
	h.getHp(), h.getHp(), h.getHp(), h.getHp(), h.getHp(), h.getHp(), h.getHp(), h.getHp();
	h.printCounter();

	return 0;
}

友元

目的:让一个类或函数能够访问另一个类的私有成员

友元的关键字:friend

三种友元:

1. 全局函数作为友元

函数作为友元,访问了People的私有变量

#include<iostream>
#include<string>
using namespace std;

class People {
	friend void friendVisit(People* p);//函数作为友元,访问了People的私有变量
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; //没有在class里加上friend void friendVisit(People* p) 前,此处报错,不能访问私有成员变量
}
int main() {
	People p;
	friendVisit(&p);
	return 0;
}

2. 类作为友元

类作为友元,访问了People的私有成员变量

#include<iostream>
#include<string>
using namespace std;

class People {
	friend class PeopleFriend;//PeopleFriend类作为友元,访问了People的私有成员变量
public:
	People() {
		m_House = "大别野";
		m_Car = "玛莎拉蒂";
	}
public:
	string m_House;
private:
	string m_Car;
};

class PeopleFriend {
public:
	PeopleFriend() {

	}
	void visit(People* p) {
		cout << "你的朋友访问了你的" << p->m_House << endl;
		cout << "你的朋友访问了你的" << p->m_Car << endl;//没有在class里加上friend class PeopleFriend前,此处报错,不能访问私有成员变量
	}
};

int main() {
	People p;
	PeopleFriend pf;
	pf.visit(&p);
	return 0;
}

3. 成员函数作为友元

类的成员函数作为友元,访问了People的私有成员变量

注意:想要作为友元的类(PeopleFriend)的定义要放在要访问私有成员的类(People)的前面,否则People定义友元时不知道PeopleFriend里有成员函数

#include<iostream>
#include<string>
using namespace std;

class People;

class PeopleFriend {
public:
	PeopleFriend() {

	}
	void visitAll(People* p);
	void visitPub(People* p);
};

class People {
	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;
}
posted @ 2025-02-27 17:19  十四2001  阅读(24)  评论(0)    收藏  举报