【C++】类和对象

文章目录

  • 封装
    • 访问权限控制
    • 成员属性设置为私有
    • 成员变量和成员函数分开存储
    • struct和class的区别
  • 对象的初始化和清理
    • 构造函数与析构函数
    • 拷贝构造函数
    • 初始化列表
    • 类作为类的成员
    • 静态成员
  • this指针
    • this指针的使用
    • 空指针可以调用成员函数
    • const修饰成员函数和对象
  • 友元
    • 全局函数作为友元
    • 类作为友元
    • 成员函数作友元
  • 继承
    • 继承的基本语法
    • 继承方式
    • 继承中的对象模型
    • 继承中的构造和析构顺序
    • 继承中的同名成员处理
  • 多态
    • 虚函数
    • 纯虚函数和抽象类
    • 虚析构和纯虚析构
  • 运算符重载

封装

访问权限控制

#include
using namespace std;

class Person {
public:
	string name;
	Person(int id, string name, string address)
	{
		this->id = id;
		this->name = name;
		this->address = address;
		cout << "公共属性:name 受保护属性:id 私有属性:address" << endl;
		print();
	}
	void print()
	{
		cout << "[+]类内 访问公共属性name:" << name <<endl;
		cout << "[+]类内 访问受保护属性id:" << id<<endl;
		cout << "[+]类内 访问私有属性address:" << address << endl;
	}

protected:
	int id;
	
private:
	string address;
};

class Student :public Person {
public:
	Student(int id, string name, string addrsss):Person(id,name,addrsss){
		print();
	}
	
	void print()
	{
		cout << "[+]子类 访问父类中的公共属性name:" << name << endl;
		cout << "[+]子类 访问父类中的受保护属性id:" << id << endl;
		cout << "[-]子类 无法访问父类中的私有属性address" << endl;
	}
};

int main()
{	
	Student stu(10, "孙悟空","灵台方寸山");
	cout << "[+]类外 访问公共属性name:" << stu.name << endl;
	cout << "[-]类外 无法访问受保护属性id" << endl;
	cout << "[-]类外 无法访问私有属性address" << endl;
	return 0;
}

【C++】类和对象_第1张图片

成员属性设置为私有

#include
using namespace std;

class Person {
private:
	string name;
	string sex;
	int age;

public:
	Person(string name,string sex,int age)
	{
		this->name = name;
		this->sex = sex;
		this->age = age;
	}
	void setName(string name)
	{
		this->name = name;
	}
	
	string getName()
	{
		return this->sex;
	}

	void setSex(string sex)
	{
		this->sex = sex;
	}

	string getSex()
	{
		return this->name;
	}

	void setAge(int age)
	{
		this->age = age;
	}

	int getAge()
	{
		return this->age;
	}
};

int main()
{
	Person p("孙悟空", "男", 1000);
	cout << "修改前的值" << endl;
	cout << "姓名:" << p.getName() << endl;
	cout << "性别:" << p.getSex() << endl;
	cout << "年龄:" << p.getAge() << endl;
	p.setName("猪八戒");
	p.setSex("男");
	p.setAge(2000);

	cout << "修改后的值" << endl;
	cout << "姓名:" << p.getName() << endl;
	cout << "性别:" << p.getSex() << endl;
	cout << "年龄:" << p.getAge() << endl;
	return 0;
}

【C++】类和对象_第2张图片

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

空对象占1个字节

#include
using namespace std;

class Person{};

int main()
{
	Person p;
	cout << sizeof(p);
	return 0;
}

【C++】类和对象_第3张图片

只有非静态成员变量才属于对象

#include
using namespace std;

class Person
{

public:
	int a;//非静态成员变量占对象空间
	static int b;静态成员变量不占对象空间
	
	Person()
	{
		a = 0;
	}
	void func()//成员函数也不占对象空间,所有函数共享一个函数实例
	{
		cout << "a:" << a << endl;
	}

	static void sfunc()//静态成员函数也不占对象空间
	{
		cout << "b:" << b << endl;
	}

};

int Person::b = 1;

int main()
{
	Person p;
	cout << sizeof(p);
	return 0;
}

【C++】类和对象_第4张图片

struct和class的区别

#include
using namespace std;

class C1 {
	int a;
};

struct C2
{
	int a;
};

int main()
{
	C1 c1;
	c1.a = 1;//错误,类的默认访问权限为私有

	C2 c2;
	c2.a = 1;//正确,结构体的访问权限一直是公共的
	return 0;
}

对象的初始化和清理

构造函数与析构函数

构造函数的分类

按参数分类
	有参构造和无参构造
	
按类型分类
	普通构造和拷贝构造

构造函数的调用方式

#include
using namespace std;

class Person {
public:
	Person() {
		id = 0;
		cout << "0无参构造函数!" << endl;
	}

	Person(int id) {
		this->id = id;
		cout << this->id << "有参构造函数!" << endl;
	}

	Person(const Person& p) {
		//const 不可修改
		//& 传入的是对象的引用
		//const Person& p 不可修改的Person对象的的引用p
		this->id = p.id;
		cout << this->id <<"拷贝构造函数!" << endl;
	}

	~Person() {
		cout << id <<"析构函数!" << endl;
	}
public:
	int id;
};


int main() {

	Person p;
	//Person p();//编译器会认为这是一个函数声明

	//括号法
	Person p1(1);
	Person p2(p1);

	//显示法
	Person p3 = Person(3);
	Person p4 = Person(p3);

	//隐式转换法
	Person p5 = 5;
	Person p6 = p5;

	Person(10);//匿名对象  特点:程序执行结束后,系统会立即回收匿名对象

	//Person(p6);//不要利用拷贝构造函数初始化匿名对象 Person(p6) 等价于 Person p6
	return 0;
}

【C++】类和对象_第5张图片

拷贝构造函数

调用规则

#include
using namespace std;
class Person {
public:
	Person() {
		cout << "无参构造函数!" << endl;
		mAge = 0;
	}
	Person(int age) {
		cout << "有参构造函数!" << endl;
		mAge = age;
	}
	Person(const Person& p) {
		cout << "拷贝构造函数!" << endl;
		mAge = p.mAge;
	}
	//析构函数在释放内存之前调用
	~Person() {
		cout << "析构函数!" << endl;
	}
public:
	int mAge;
};

//1. 使用一个已经创建完毕的对象来初始化一个新对象
void test01() {

	Person man(100); //p对象已经创建完毕
	Person newman(man); //调用拷贝构造函数
	Person newman2 = man; //拷贝构造

	//Person newman3;
	//newman3 = man; //不是调用拷贝构造函数,赋值操作
}

//2. 值传递的方式给函数参数传值
//相当于Person p1 = p;
void doWork(Person p1) {}
void test02() {
	Person p; //无参构造函数
	doWork(p);
}

//3. 以值方式返回局部对象
Person doWork2()
{
	Person p1;
	cout << (int*)&p1 << endl;
	return p1;
}

void test03()
{
	Person p = doWork2();
	cout << (int*)&p << endl;
}


int main() {

	//test01();
	//test02();
	test03();

	return 0;
}

【C++】类和对象_第6张图片

#include
using namespace std;

class Gz 
{
public:
	Gz() { cout << "默认构造函数\n"; }
	Gz(const Gz& x) { cout << "拷贝构造函数\n"; }
};

//1.值传递的方式给函数参数传值时调用拷贝函数
Gz test(Gz x) 
{
		//2.用一个已经创建完毕的对象来初始化一个新对象时调用拷贝构造函数
		Gz c(x);
		//3.以值的形式返回局部对象时调用拷贝构造函数
		return c;
}

int main() 
{
	Gz a, b;
	b = test(a);	
	return 0;
}
  • 使用一个已经创建完毕的对象来初始化一个新对象
  • 值传递的方式给函数参数传值
  • 以值方式返回局部对象

初始化列表

#include
using namespace std;
class Person {
public:

	传统方式初始化
	//Person(int a, int b, int c) {
	//	m_A = a;
	//	m_B = b;
	//	m_C = c;
	//}

	//初始化列表方式初始化
	Person(int a, int b, int c) :m_A(a), m_B(b), m_C(c) {}
	void PrintPerson() {
		cout << "mA:" << m_A << endl;
		cout << "mB:" << m_B << endl;
		cout << "mC:" << m_C << endl;
	}
private:
	int m_A;
	int m_B;
	int m_C;
};

int main() {

	Person p(1, 2, 3);
	p.PrintPerson();

	return 0;
}

【C++】类和对象_第7张图片

类作为类的成员

#include
using namespace std;

class Phone 
{
public:
	string name;
	Phone(string name):name(name)
	{
		cout << "Phone构造函数" << endl;
	}
	
	~Phone()
	{
		cout << "Phone析构函数" << endl;
	}
};

class Person 
{
public:
	string name;
	Phone phone;
	Person(string person_name,string phone_name):name(person_name),phone(phone_name)
	{
		cout << "Person构造函数" << endl;
	}

	~Person()
	{
		cout << "Person析构函数" << endl;
	}
	void playGame()
	{
		cout << name <<"正在使用" << phone.name <<"打游戏!"<< endl;
	}
};
int main() {
	Person p("猪八戒", "爱疯X");
	p.playGame();

}

【C++】类和对象_第8张图片

  • 构造函数的执行顺序:先调用对象成员的构造,再调用本类构造
  • 析构函数的执行顺序:与构造函数的执行顺序相反

静态成员

静态成员变量

#include
using namespace std;

class Person 
{
public:
	static int a;

private:
	static int b;

};
//必须在全局中初始化,初始化时需要类型声明
int Person::a = 10;
int Person::b = 10;

int main() {
	
	Person p1;
	p1.a = 100;
	cout << p1.a << endl;//通过对象访问

	Person p2;
	p2.a = 200;
	cout << p1.a << endl;//不同的对象共享同一份数据
	cout << p2.a << endl;

	cout << Person::a << endl;//通过类名访问

	//私有属性无法访问
	//cout << p1.b << Person::b << endl;
	return 0;
}
  • 静态成员变量可以通过类名::成员变量()对象.成员变量()访问
  • 私有的静态成员变量不可以在类外访问

静态成员函数

#include
using namespace std;

class Person
{
public:
	static int a;
	int b;
	static void func()
	{
		cout << "静态成员函数func1被调用" << endl;
		a = 100;
		//b = 100;//静态成员函数不能访问非静态成员变量
	}

private:
	static void func2()
	{
		cout << "静态成员函数func2被调用" << endl;
	}
};

int Person::a = 1;
int main() {

	Person p1;
	p1.func();     //通过对象访问
	Person::func();//通过类名访问
	
	//私有的成员函数无法访问
	//p1.func2();
	//Person::func2();

	return 0;
}	
  • 静态成员函数可以通过类名::成员函数()对象.成员函数()访问
  • 私有静态成员函数不可以在类外访问

this指针

this指针的使用

#include
using namespace std;

class Person 
{
public:
	int age;
	Person(int age) 
	{
		this->age = age;//解决形参和成员变量的命名冲突
	}

	Person& PersonAddPerson(Person p)
	{
		this->age += p.age;
		return *this;//返回对象本身,实现链式编程
	}
};


int main() {
	Person p1(10),p2(10),p3(10);

	p1.PersonAddPerson(p2).PersonAddPerson(p3);

	cout << p1.age << endl;
	return 0;
}	

【C++】类和对象_第9张图片

  • 解决形参和成员变量的命名冲突
  • 实现链式编程

空指针可以调用成员函数

#include
using namespace std;

class Person 
{
public:
	void showClassName()
	{
		cout << "我是Person类" << endl;
	}
	void showPerson()
	{
		if (this == NULL)return;//如果this为空指针时,停止接下来的涉及成员变量操作
		cout << name << endl;
	}
	string name;
};

int main() {
	Person* p = NULL;
	//空指针可以访问成员函数
	p->showClassName();
	//空指针不能访问带有成员变量的成员函数
	//p->showPerson();

	//空指针不能访问成员变量
	//cout << p->name << endl;
	return 0;
}	

【C++】类和对象_第10张图片

  • 空指针可以访问不含成员变量的成员函数
  • 空指针不能访问成员变量

const修饰成员函数和对象

#include
using namespace std;

class Person 
{
public:
	int a;
	mutable int b;
	Person()
	{
		a = 100;
		b = 0;
	}
	void thisPoint()
	{
		//this = NULL;//错误,this指针是指针常量 本质是Person* const p 不可以修改指向;
		//this->a = 100;//正确,this指针指向的数据是可以修改的
	}
	void showPerson()const
	{
		//成员变量 和 this->成员变量 等价
		b = 100;
		this->b = 200;

		cout << b << endl;
		cout << this->b << endl;
	}
	void showClassName()
	{
		cout << "我是Person类!" << endl;
	}
	void myFunc() 
	{
		a = 200;
	}
};

int main() {
	const Person person;     //定义常对象
	cout << person.a << endl;//常对象可以访问成员变量
	person.b = 100;          //常对象可以修改mutable修饰的成员变量
	person.showPerson();     //常对象只能访问常函数和成员变量
	//person.myFunc();       //错误,myFunc成员函数中对成员变量进行了修改操作

	return 0;
}	

【C++】类和对象_第11张图片

  • 常对象只能访问常函数和成员变量
  • 常对象只能修改mutable修饰的成员变量

友元

全局函数作为友元

#include
using namespace std;

class Building 
{
	friend void goodGay(Building* building);
public:
	string sittingRoom;
	Building()
	{
		this->sittingRoom = "客厅";
		this->bedRoom = "卧室";
	}
private:
	string bedRoom;
};

void goodGay(Building* building)
{
	cout << "好基友正在访问" << building->sittingRoom << endl;
	cout << "好基友正在访问" << building->bedRoom << endl;
}

int main() {
	Building building;
	goodGay(&building);
	return 0;
}	

【C++】类和对象_第12张图片

  • 声明全局函数作为类的友元:fiend 数据类型 函数名([参数列表])

类作为友元

#include
using namespace std;

class Building 
{
	friend class GoodGay;
public:
	string sittingRoom;
	Building()
	{
		this->sittingRoom = "客厅";
		this->bedRoom = "卧室";
	}

private:
	string bedRoom;
};

class GoodGay {
public:
	GoodGay()
	{
		building = new Building;
	}
	void visit()
	{
		cout << "好基友正在访问" << building->sittingRoom << endl;
		cout << "好基友正在访问" << building->bedRoom << endl;
	}
private:
	Building* building;
};
int main() {
	GoodGay goodgay;
	goodgay.visit();
	return 0;
}	

【C++】类和对象_第13张图片

  • 声明一个类作为另一个类的友元:friend class 类名

成员函数作友元

#include
using namespace std;
class Building;//声明友元的类需要先声明,有友元函数的类,内部函数需要在外部实现
class GoodGay
{
public:

	GoodGay();
	void visit(); //只让visit函数作为Building的好朋友,可以发访问Building中私有内容

private:
	Building* building;
};

class Building
{
	friend void GoodGay::visit();
public:
	Building()
	{
		this->m_SittingRoom = "客厅";
		this->m_BedRoom = "卧室";
	}
public:
	string m_SittingRoom; //客厅
private:
	string m_BedRoom;//卧室
};

GoodGay::GoodGay()
{
	building = new Building;
}

void GoodGay::visit()
{
	cout << "好基友正在访问" << building->m_SittingRoom << endl;
	cout << "好基友正在访问" << building->m_BedRoom << endl;
}

int main() {
	GoodGay  goodgay;
	goodgay.visit();
	return 0;
}

【C++】类和对象_第14张图片

  • 声明成员函数作为类的友元: friend 数据类型 类名::函数名([参数列表])
  • 声明友元的类需要先用class 类名进行声明

继承

继承的基本语法

#include
using namespace std;

class Animal {
public:
	string color;
	Animal(string color):color(color){}
	void speak()
	{
		cout << "我是一个动物!" << endl;
	}
	void run()
	{
		cout << "会跑!" << endl;
	}
	void sleep()
	{
		cout << "会睡觉!" << endl;
	}
	void eat()
	{
		cout << "会吃!" << endl;
	}
};


class Dog :public Animal 
{
public:
	Dog(string color):Animal(color){}
	//重写父类中的speak方法
	void speak()
	{
		cout << "我是"<<color<<"的狗狗!"<< endl;
	}

};

class Cat :public Animal 
{
public:
	Cat(string color):Animal(color){}
	//重写父类中的speak方法
	void speak()
	{
		cout << "我是" <<color<<"的猫猫!" << endl;
	}
};

int main() {
	
	Dog dog("黑色");
	dog.speak();
	dog.eat();
	dog.sleep();
	dog.run();

	Cat cat("金黄色");
	cat.speak();
	cat.eat();
	cat.sleep();
	cat.run();

	return 0;
}

继承方式

#include
using namespace std;
class Base 
{
public:
	Base()
	{
		a = 1;
		b = 2;
		c = 3;
	}
public:
	int a;
protected:
	int b;
private:
	int c;

};

class Son1 :public Base 
{
public:
	void func()
	{
		cout << "Base类 <----公共继承----  Son1类" << endl;
		cout << "public a    ----------->  public a=" << a << endl;
		cout << "protected b ----------->  protected b=" << b << endl;
		cout << "private c   ----------->  存在本类中,但不可访问" << endl << endl;;
	}
};

class Son2 :protected Base
{
public:
	void func()
	{
		cout << "Base类 <----保护继承----  Son2类" << endl;
		cout << "public a    ----------->  protected a=" << a << endl;
		cout << "protected b ----------->  protected b=" << b << endl;
		cout << "private c   ----------->  存在本类中,但不可访问" << endl << endl;;
	}

};

class Son3 :private Base
{
public:
	void func()
	{
		cout << "Base类 <----私有继承----  Son3类" << endl;
		cout << "public a    ----------->  private a=" << a << endl;
		cout << "protected b ----------->  private b=" << b << endl;
		cout << "private c   ----------->  存在本类中,但不可访问" << endl << endl;;
	}
};


int main() 
{
	Son1 son1;
	son1.func();

	Son2 son2;
	son2.func();

	Son3 son3;
	son3.func();

	return 0;
}

【C++】类和对象_第15张图片

  • 继承的三种方式:公共继承 保护继承 私有继承

继承中的对象模型

#include
using namespace std;

class Base 
{
public:
	int a;
protected:
	int b;
private:
	int c;

};

class Son :public Base 
{
public:
	int d;
};

int main() 
{
	cout << sizeof(Son) << endl;
	return 0;
}

【C++】类和对象_第16张图片

  • 父类中私有成员也是被子类继承下去了,只是由编译器给隐藏后访问不到

继承中的构造和析构顺序


继承中的同名成员处理


多态

虚函数

纯虚函数和抽象类

虚析构和纯虚析构

运算符重载

你可能感兴趣的:(C/C++)