C++中的类和对象(一:初识类和对象)

面向过程和面向对象的初步认识

C语言是基于面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。

C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。

一:类的定义

class为定义类的关键字,Person为类的名字,{}中为类的主体,注意类定义结束时后面的分号。

类中的元素称为类的成员:类中的数据称为类的属性或者成员变量; 类中的函数称为类的方法或者成员函数。

成员函数的声明和定义可以全部放在类体中,也可以将声明放在 .h 文件中,定义放在.cpp文件中。

  • 举个栗子
class Person{
public:
	// 成员函数
	void PrintPerson();
private:
	// 成员变量
	char _name[20];
	char _gender[3];
	int _age;
	……
};
// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo(){
	cout<<_name<<" "_gender<<" "<<_age<<endl;
}

二:类的访问限定符及封装

  • 访问限定符

public: 修饰的成员可以在类外被访问(公有的)

private: 修饰的成员在类外不能直接被访问(私有的)

class的默认访问权限为private | struct的默认访问权限为public(兼容C)

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

【面试题】: C++中的struct和class的区别是什么?

解答:C++是兼容C语言的,C++中的struct可以当成结构体使用。另外C++中struct还可以用来定义类,struct定义类和class定义类相似,区别是struct的成员默认访问权限为public,class的成员默认访问权限为private。

  • 封装

封装从字面上来理解就是包装的意思,专业点就是信息的隐藏。

封装: 封装本质上是一种管理,用类将数据和操作数据的方法结合起来,通过访问限定符隐藏对象的属性和实现细节,仅公开接口与外部交互。

也就是说用户是无需知道对象内部的细节,但可以通过该对象对外的提供的接口来访问该对象。

封装的优点: 提高了数据的安全性(外部不能随意访问私有的成员属性)、提高了代码的可维护性(只需要修改类就可以)、降低了代码的耦合度(使代码模块化)。

三:类的实例化

类的实例化:用类创建对象的过程

  1. 类只是一个模型,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它。
  2. 一个类可以实例化出多个对象,对象占用实际的物理空间,存储类的成员变量。

类相当于设计图纸(设计出来什么东西,但实际不占空间)对象相当于使用图纸建造出来的房子。

  • 举个栗子
class AddClass{
private:
	int _num1;
	int _num2;
public:
	//默认内联但为了可读性我们还是加上内联的标志
	inline void GetNum1(int num1){
		_num1 = num1;
	}
	inline void GetNum2(int num2){
		_num2 = num2;
	}
	//在类内声明
	int AddNum();
};
//在类外定义
int AddClass::AddNum(){
	return _num1 + _num2;
}

int main(){
	AddClass add;//类的实例化
	add.GetNum1(1);//成员调用
	add.GetNum2(2);
	cout << add.AddNum() << endl;
}

四:如何计算类对象的大小

类中既有成员变量,又有成员函数,那么一个类的对象中保存了什么?如何计算一个类的大小?

要计算类对象的大小,首先我们得搞清楚类对象中包含了什么。

  • 对象中只保存成员变量,成员函数放在公共代码段

每个对象中成员变量是不同的,但都是调用同一份成员函数,当一个类创建多个对象时,每个对象如果都保存一份代码,相当于相同代码保存多次,会造成空间的浪费,所以对象中只保存成员变量,成员函数放在公共代码段。

帮助理解: 类实例化出很多个人(对象),这些人都有不同的年龄或者姓名(成员变量),但是显示它们姓名和年龄的函数(成员函数)都是一样的。

  • 类对象的大小计算遵循结构体内存对齐规则

1.第一个成员在与结构体变量偏移位为0的地址处
2.其他成员变量要对齐到对齐数整数倍的地址处

对齐数 = 编译器默认的对齐数(VS为8、Linux为4) 与 该成员大小的较小值

3.结构体的总大小为最大对齐数的整数倍
4.嵌套的结构体对齐到自己最大对齐数的整数倍,结构体的整体大小就是所有最大对齐数的整数倍。
在这里插入图片描述

五:this指针

我们类中的函数都存在公共代码段,那么编译器使怎么区分是哪个对象调用了成员函数呢?

这就牵扯到了每个类中隐藏的成员this指针

  • 什么是this指针

this指针是一个指向对象自身的指针

this指针会默认作为成员函数调用的第一个参数,将调用成员函数的对象地址传入this,在函数内部找到对象中的成员,this指针这个形参是隐式的,它并不出现在代码中,而是在编译阶段由编译器将它添加到参数列表中。

成员函数最终被编译成与对象无关的普通函数,除了成员变量,会丢失所有信息,所以编译时要在成员函数中添加一个额外的参数,把当前对象的首地址传入,以此来关联成员函数和成员变量。这个额外的参数,实际上就是 this指针,它是成员函数和成员变量关联的桥梁。

实际上我们调用的代码是这样传参的:

class AddClass{
private:
  int _num1;
  int _num2;
public:
  //默认内联但为了可读性我们还是加上内联的标志
  inline void GetNum1(int num1)
  inline void GetNum1(AddClass* this, int num1){
    _num1 = num1;
  }
  inline void GetNum2(int num2){
    _num2 = num2;
  }
  //在类内声明
  int AddNum();
  int AddNum(AddClass* this);
};
//在类外定义
int AddClass::AddNum(){
  return _num1 + _num2;
}
int main(){
  AddClass add;
  add.GetNum1(1);
  add.GetNum1(&add, 1);
  add.GetNum2(2);
  cout << add.AddNum() << endl;
  AddNum(&add);
}
  • this指针的特性

1.this指针不存储在类中,每个编译器对this指针存储的地方都有所不同,在vs中this指针存储在寄存器中
2.this指针可以为空,但是一旦调用,需要访问对象中成员变量就会由于this为空发生内存越界(在对象开辟的空间上去找成员变量)而导致崩溃

小结

类和对象是让C++ 得以实现面向对象,得以更加方便的进行大型项目编程的最重要的部分

技术就如同武术,基本功很重要,只要基本功扎实了,再去学习更深层次的东西就会比较容易,只要明白其原理,举一反三就能达到“无招胜有招”的最高境界

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值