C++类和对象(1)

C++类和对象(1)

如果我想把人这个对象封装起来。
经过C语言的学习,我们可以使用结构体,里面可以定义人的种种数据。
但是如果这个人的一些数据是涉及隐私的,不想让用户知道的,该怎么办呢?
这就是今天我们学习的类与结构体的核心区别。

1.类的定义

如果是结构体,我们这样定义。

c 复制代码
struct Date
{
	int _year;
	int _month;
	int _day;

};

如果是类,我们这样定义。

c 复制代码
class Date {
public:
	void Init(int year, int month, int day) {
		_year = year;
		_month = month;
		_day = day;
	}//成员函数
	void Print() {
	cout << _year << "/" << _month << '/' << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;//成员变量
};

class为类的关键字,后面是类名,{}中是类的主体。

类体中内容称为类的成员:类中的变量称为类的属性或成员变量,类中的函数称为类的方法或成员函数。

因为有了在成员变量前面加了private:所以我们在除了类中的所有地方都不能直接访问这个类的成员函数。

成员函数默认为inline

2.访问限定符

分为三个:public,private,protected

在现阶段的学习中我们可以暂且认为private与protected作用一样。

class定义成员时没有被访问限定符修饰时默认为private

3.类域

类定义出了一个新的作用域。在类外定义成员时,需要加上::作用域操作符指明成员属于哪个类域

c 复制代码
class Date {
public:
	void Init(int year, int month, int day) {
		_year = year;
		_month = month;
		_day = day;
	}
	void Print();
private:
	int _year;
	int _month;
	int _day;
};
void Date::Print() {
	cout << _year << "/" << _month << '/' << _day << endl;
}

4.对象的大小

在C语言学习时,我们学习了如何判断结构体的大小与内存对齐规则。

C++也规定实例化的对象要符合内存对齐的规则。

  • 第一个成员在于结构体偏移量为0的地址处
  • 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处
  • 对齐数 =(编译器默认的一个对齐数)与(该成员大小)的较小值
  • vs中默认对齐数是8
  • 最大对齐数 =(所有变量类型最大者)与(默认对齐数)取较小
  • 结构体总大小为最大对齐数的整数倍

注意

对象中不存储成员函数,因为函数被编译后是一段指令,它们无法存储在对象中。这些指令存储在单独的区域(代码段)。

c 复制代码
#include<iostream>
using namespace std;
// 计算⼀下A/B/C实例化的对象是多⼤? 
class A
{
public:
	void Print()
	{
		cout << _ch << endl;
	}
private:
	char _ch;
	int _i;
};
class B
{
public:
	void Print()
	{
		//...
	}
};
class C
{
};
int main()
{
	A a;
	B b;
	C c;
	cout << sizeof(a) << endl;
	cout << sizeof(b) << endl;
	cout << sizeof(c) << endl;
	return 0;
}

为什么b和c的大小是1呢?完全是因为要代表这个对象存在,不得不分配一个字节来说明其存在。

5.this指针

以上面的Date类为例,当我们创建了两个对象的d1.d2并调用成员函数时,该函数是如何知道应该访问d1还是d2呢?

编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this指针。比如Date类的Init的真实原型:

void Init ( Date* const this, int year, int month, int day )

  • 类的成员函数中访问成员变量,本质都是通过this指针访问的,如Init函数中给_year赋值, this->_year = year;
  • C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显示使用this指针。

所以其实void Init( int year, int month, int day)就等价于

void Init(Date* const this, int year, int month, int day)

接下来是两道经典例题

c 复制代码
#include<iostream>
using namespace std;
class A
{
public:
	void Print()
	{
		cout << "A::Print()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->Print();
	return 0;
}

A.编译报错 B.运行崩溃 C.正常运行
注意 :
当指针指向的内容是对象时,用它调用类中变量和函数的本质(类似p->Print())是将自己传给this指针。并非真正的解引用。

当我们调试转到反汇编时:

所以p->Print();实际上并没有发生解引用这一步,自然不会报错。

所以选C

c 复制代码
#include<iostream>
using namespace std;
class A
{
public:
	void Print()
	{
		cout << "A::Print()" << endl;
		cout<<_a<<endl;
	}
private:
	int _a;
};
int main()
{
	A* p =nullptr;
	p->Print();
	return 0;
}

A.编译报错 B.运行崩溃 C.正常运行

在Print函数中,_a就是this->_a,而p指针是空指针,所以this也是空指针,所以会运行错误。

如有错误,欢迎打在评论区。
主页还有更多优质内容OvO

相关推荐
weixin_436525073 小时前
Gitee - IDEA 主支 master 和分支 dev 的使用
java·ide·intellij-idea
_屈臣_3 小时前
卡特兰数【模板】(四个公式模板)
c++·算法
sheji34164 小时前
【开题答辩全过程】以 YF精品视频动漫平台为例,包含答辩的问题和答案
java·eclipse
渡我白衣4 小时前
C++ 异常处理全解析:从语法到设计哲学
开发语言·c++·面试
小蕾Java4 小时前
Java 开发工具,最新2025 IDEA 使用
java·ide·intellij-idea
是席木木啊4 小时前
Idea升级到2024版本:“marketplace plugins are not loaded”解决方案
java·ide·intellij-idea
胚芽鞘6814 小时前
博客标题:解密 IntelliJ IDEA 调试:当你的 List 不仅仅是 List
java·ide·intellij-idea
꒰ঌ 安卓开发໒꒱4 小时前
Java面试-并发面试(一)
java·jvm·面试
HezhezhiyuLe4 小时前
IDEA中Add New Configuration找不到Tomcat
java·ide·intellij-idea