IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++_类与对象介绍 -> 正文阅读

[C++知识库]C++_类与对象介绍

C++与C语言的重要区别之一就是,C语言是面向过程编程,C++是面向对象编程,C++中加入了类和对象,因此C++很多情况下更加适合开发大型项目。本篇博客将简单介绍面向对象编程的思想,梳理C++中类和对象的相关基础语法。

面向过程与面向对象

我的个人理解是:面向过程关注的是做某一件事情的具体过程,就是把做某件事的过程拆成一个个步骤,然后按照顺序来执行每一个步骤,执行完所有步骤之后就完成了这件事情;面向对象关注的是某件事情中涉及到的对象以及对象之间的交互,就是分析某件事情是由哪几类对象构成,然后考虑这些对象使用哪些方法来解决这件事情。
面向过程与面向对象具体的特点和优缺点,这篇博客中不详细介绍。

类和对象

struct在C++中的变化

C++是兼容C语言语法的,因此C++中也有struct关键字。在C语言中的struct是用来标识结构体类型的关键字,到了C++中,struct有了新的变化,struct结构体得到了扩充。C语言里面struct中只能定义变量,而C++struct中可以定义变量和函数。

struct Student
{
	// 为了区分和函数中的形参名,一般对成员变量名前面或后面加_,或者前面加m
	char _name[10];
	int _age;
	int _id;

	// 成员方法/函数
	void Init(const char* name, int age, int id)
	{
		strcpy(_name, name);
		_age = age;
		_id = id;
	}

	void Print()
	{
		cout << _name << endl;
		cout << _age << endl;
		cout << _id << endl;
	}

};

int main()
{
	struct Student s1; // 兼容C
	Student s2; // 升级到类,Student是类名,也是类型

	// 类的处理方式,不需要像C结构体对象一样每个成员变量赋值,可以用一个函数一次性赋值
	s1.Init("zhangsan", 18, 202108101);
	s1.Print();

	return 0;
}

C++兼容C里面结构体的用法,同时struct在C++中也升级成了类。

类的定义

class classname
{
    // 成员变量
    
    // 成员函数
};

class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。
类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数

类的两种定义方式:

  1. 声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
  2. 类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::

一般来说使用方式2会更好。

类访问限定符

C++的优点之一就是封装,封装就是:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。

封装是一种更好的严格管理

  1. 数据和方法都封装到类里面
  2. 可以给你访问的定义成共有,不想给你访问的定义成私有

具体的实现方式就是用类访问限定符来修饰成员变量和方法,控制访问权限。

类访问限定符:

  • public(公有)
  • protect(保护)
  • private(私有)

访问限定符说明

  1. public修饰的成员在类外可以直接被访问
  2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
  3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
  4. 如果后面没有访问限定符,作用域就到 } 即类结束。
  5. class的默认访问权限为private,struct默认为为public(因为struct要兼容C)

注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别

// 面向对象三大特性:封装、继承、多态
// 封装 : 1.数据和方法放在一起  2. 访问限定符
// struct 默认都是public , class 默认都是是private
// 一般定义的时候不要用默认的限定符,指明限定符更好。
class Student
{
	// 成员变量
private:
	char _name[10];
	int _age;
	int _id;

	// 成员方法/函数
public:
	void Init(const char* name, int age, int id)
	{
		strcpy(_name, name);
		_age = age;
		_id = id;
	}

	void Print()
	{
		cout << _name << endl;
		cout << _age << endl;
		cout << _id << endl;
	}

};
int main()
{
	struct Student s1; // 兼容C
	Student s2; // 升级到类,Student是类名,也是类型

	// 类的处理方式,不需要像C结构体对象一样每个成员变量赋值,可以用一个函数一次性赋值
	s1.Init("zhangsan", 18, 202108101);
	s1.Print();

	return 0;
}

类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用::作用域操作符指明成员属于哪个类域。

原因:不同类可能会有重名的变量

class Person
{
public:
	void PrintPersonInfo();
private:
	char _name[20];
	char _gender[3];
	int _age;
};

// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo()
{
	cout << _name << " "<< _gender << " " << _age << endl;  
}

类对象的大小

对于类的不同对象,他们的成员变量的值是各不相同的,但是成员函数都是一样的,所以每个类对象只需要存储成员变量,将成员函数存在公共代码区,用到的时候调用即可。
类对象的存储结构如下:
在这里插入图片描述
结论:计算类或者类对象大小(类的大小就是类对象的大小),只看成员变量,考虑内存对齐,C++内存对齐规则和C结构体一致。

class A1
{
public:
	int _a;
public:
	void func() {}

};

class A2
{
public:
	void func() {}

};

class A3
{
};

int main()
{
	cout << sizeof(A1) << endl; // 4

	// 空类会给1byte,用来标识该类
	cout << sizeof(A2) << endl; // 1
	cout << sizeof(A3) << endl; // 1

	return 0;
}

对象实例化

用类类型创建对象的过程,称为类的实例化

  1. 类是对对象进行描述的,类似于一个模型,描述了类有哪些成员,当我们定义出一个类时并没有分配实际的内存空间来存储它;
  2. 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量Person类是没有空间的,只有Person类实例化出的对象才有具体的年龄。
  3. 举例来说,类就像一个建筑的设计图,描述了建筑的样式,建筑实际上并不存在,而实例化出的对象就是照着设计图建造出来的实体建筑,是实际存在的。

this指针

Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调用 Init 函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?
C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

// 函数内部区分是哪个对象调用成员函数的方式: 有一个隐形的参数this
// 调用成员函数时不能显式传实参给this,定义成员函数时也不行写this,在成员函数内部可以写this
class Date
{
public:
	
	// void Init(Date* const this, int year, int month, int day) -- 实际上
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;

		// 实际上 -- 一般情况下不需要显式写出来
		// this->_year = year;
		// this->_month = month;
		// this->_day = day;

	}

	// void Print(Date* const this) -- 实际上
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
		// cout << this->_year << "-" << this->_month << "-" << this->_day << endl; -- 实际上
	}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1;
	d1.Init(2022, 9, 23); // d1.Init(&d1, 2022, 9, 23);
	d1.Print(); // d1.Print(&d1);

	Date d2;
	d2.Init(2022, 9, 27);// d2.Init(&d2, 2022, 9, 27);
	d2.Print(); // d2.Print(&d2);

	return 0;
}

this指针存在哪?
this指针是临时变量,所以存在栈帧里面,有些编译器会放到寄存器中。VS会将它放到ecx寄存器中。

this指针可以为空吗?
是可以的,语法不一定会错,但是逻辑上很可能会有问题。

class A
{
public:
	void show()
	{
		cout << "show()" << endl;
	}

private:
	int _a;
};

class B
{
public:
	void Print()
	{
		cout << _a << endl;
	}

private:
	int _a;
};

int main()
{
	A* p1 = nullptr;
	p1->show(); // 正常运行

	B* p2 = nullptr;
	p2->Print();// 程序崩溃

	/* 分析
	*  对于p1
	*  1. p1虽然是空指针,但是p1调用成员函数不会编译报错,因为空指针不是语法错误,编译器不会检查出来
	*  2. p1虽然是空指针,但是p1调用成员函数不会出现空指针访问,因为成员函数没有存在对象里面,而是存在公共区,
	*	  空指针调用成员函数接相当于直接call这个函数
	*  3. 这里虽然不会报错,但是会把p1作为实参传递给隐藏this指针,只要不对空指针进行解引用,就不会报错
	* 
	*  对于p2
	*  4. p2与p1在第三点上是不一样的,因为p2后面使用了this指针,而空指针是找不到成员变量的
	*/

	return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:22:12  更:2022-10-08 20:26:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 9:08:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码