C++ 类和对象(一)类、访问限定符、this指针

这篇具有很好参考价值的文章主要介绍了C++ 类和对象(一)类、访问限定符、this指针。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C++ 类和对象(一)类、访问限定符、this指针,C++,开发语言,c++

前言

        C++中的类(class)是实现数据抽象和面向对象程序设计的核心。本文作为类和对象的开篇,将介绍有关类的基础知识,之后会持续更新类和对象的深入内容。

目录

前言

1 类的引入

2 类的定义

3 访问限定符和封装

3.1 访问限定符

3.2 封装

4 类的实例化及类对象的储存

4.1 实例化

4.2 类对象的储存

4.3 类的大小计算

5 this指针

5.1 this指针的引入

5.2 this能否为空指针

5.3 代码规范


1 类的引入

 C++兼容C语言,C语言中的结构(struct)在C++中扩充成了类。

struct Stack
{
    // ...
};

struct Stack st1; // C语言定义结构体变量

Stack st2;       // C++创建类对象

 C语言结构体中只能定义变量,在C++中,结构体不仅可以定义变量,也可以定义函数。

struct Stack
{
	// 成员函数
	void Init()
	{
		a = nullptr;
		top = capacity = 0;
	}

	void Push(int x)
	{
		// ...
	}

	// 成员变量
	int* a;
	int top;
	int capacity;
};

Stack st;
st.Init();  // 使用:类对象.成员变量/成员函数
st.Push(1);

2 类的定义

class className

{

        // 类体

};

class为定义类的关键字,className为类的名字,{}中为类的主体。类体中的内容为类的成员:成员变量(类的属性),成员函数(类的方法)。

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

类的定义方式:

        1.声明和定义全部放在类体中。成员函数在类中定义可能会被编译器当作内联函数处理。

        2.类声明放在.h文件中,成员函数定义放在.cpp文件中(成员函数前需加 类名::

3 访问限定符和封装

3.1 访问限定符

访问限定符分为:public(公有),protected(保护)和private(私有)

说明:

  • public修饰的成员在类外可以直接被访问
  • protected和private修饰的成员在类外不能直接被访问
  • 作用域从该访问限定符开始直到下一个访问限定符出现或类结束
  • class的默认访问权限为private,struct为public

3.2 封装

将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

// .h文件中声明成员函数
class Stack
{
public:
	void Init();
	void Push(int x);
	int Top();
private:
	int* a;
	int top;
	int capacity;
};

// .cpp文件中定义成员函数
void Stack::Init()
{
	a = nullptr;
	top = capacity = 0;
}
void Stack::Push(int x)
{
	if (top == capacity)
	{
		int newCapacity = (capacity == 0 ? 4 : capacity * 2);
		int* tmp = (int*)realloc(a, sizeof(int) * newCapacity);
		if (tmp == nullptr)
		{
			perror("relloc fail");
			return;
		}
		a = tmp;
		capacity = newCapacity;
	}
	a[top++] = x;
}
int Stack::Top()
{
	return a[top - 1];
}
int main()
{
	Stack st;
	int top = st.Top();
	// st.a[st.Top]  不能访问
	return 0;
}

如上定义栈类(Stack),成员变量top初始为0指向栈顶元素下一个位置,用户可能认为top指向栈顶元素,通过访问成员变量获取栈顶元素(st.a[st.top])出错,因此通过将Stack进行封装,将类的属性设为私有,用类的方法Top()实现获取栈顶元素供用户使用。

4 类的实例化及类对象的储存

4.1 实例化

        用类创建对象的过程称为类的实例化。类就像是一种模型,对对象进行描述,限定了类有哪些成员,定义一个类并没有分配实际的空间来储存它,一个类可以实例化出多个对象,实例化出的对象才占用实际的物理空间。

4.2 类对象的储存

        定义一个类,它的成员变量实际是一种声明,只有实例化出的对象才会定义这些成员变量,因此实例化类对象需要开辟物理空间储存成员变量,那么类的成员函数需要每个对象储存吗,类的成员函数不仅要在类中声明,也要在类中定义,每个对象都可以使用类的成员函数,所以类的成员函数不需要实例化对象储存,事实上它们也不需要类储存,因为它们存放在公共代码区。

C++ 类和对象(一)类、访问限定符、this指针,C++,开发语言,c++

4.3 类的大小计算

        那么计算类的大小只需要计算类中的成员变量,其计算方式遵循结构体内存对齐规则。

结构体内存对齐规则

1. 第一个成员在与结构体偏移量为0的地址处。

2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。

VS中默认的对齐数为8

3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。

4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

如创建三个类,它们分别是空类、只含成员函数的类、只含成员变量的类、含成员变量和成员函数的类,分别计算它们的大小。

// 空类
class A
{

};
// 类中仅有成员函数
class B
{
public:
	void Func()
	{

	}
};
// 类中仅有成员变量
class C
{
private:
	int a;
	int b;
	int c;
};
// 类中既有成员函数又有成员变量
class D
{
public:
	void Func()
	{

	}
private:
	int a;
	int b;
	int c;
};
int main()
{
	cout << "sizeof(A) " << sizeof(A) << endl;
	cout << "sizeof(B) " << sizeof(B) << endl;
	cout << "sizeof(C) " << sizeof(C) << endl;
	cout << "sizeof(D) " << sizeof(D) << endl;
	return 0;
}

结果:

C++ 类和对象(一)类、访问限定符、this指针,C++,开发语言,c++

C类含3个整型其大小为12字节,D类和C类的大小相同,可以验证成员函数不需要类储存,A类和B类的大小都为1,是因为编译器给空类(包括只含成员函数的类)一个字节用来标识。

5 this指针

5.1 this指针的引入

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;
};
int main()
{
	Date d1;
	Date d2;
	d1.Init(2022, 7, 20);
	d2.Init(2022, 7, 21);
	return 0;
}

如上定义一个日期类,创建两个对象d1,d2,类中的函数没有关于不同对象的区分,当d1调用Init()函数时,函数是如何将参数传给对象d1的成员变量(_year,_month,_day)而不是对象d2的呢?

C++中引入this指针解决该问题,即:类的每个成员函数有一个隐藏的指针参数this,当对象调用函数时会将对象的地址传给函数的this指针,函数内所有成员变量的操作都通过this指针去访问。this指针的设置和传参由编译器自动完成,用户不能显式写出,在函数体内可以使用。

this指针的特性:

  1. this指针的类型:类类型* const,在成员函数中不能给this指针赋值。
  2. this指针是成员函数的第一个隐含指针形参,对象调用成员函数时将对象地址作为实参传递给this指针,对象中不储存this指针
  3. this指针由编译器通过ecx寄存器自动传递,不需要用户传递

函数调用实际实现如下:

void Init(Date* const this, int year, int month, int day)
    {
        this->_year = year;
        this->_month = month;
        this->_day = day;
    }
    void Print(Date* const this)
    {
        cout << this->_year << '/' << this->_month << '/' << this->_day << endl;
    }

d1.Init(&d1, 2022, 7, 20);
d1.Print(&d1);

C++ 类和对象(一)类、访问限定符、this指针,C++,开发语言,c++

C++ 类和对象(一)类、访问限定符、this指针,C++,开发语言,c++

 通过验证,发现:对象d1,d2调用Init()和Print()函数时,函数的this指针的值和它们本身地址相同。

5.2 this能否为空指针

在一般情况下,不能对空指针进行解引用操作,所以类对象的指针不能为空,this指针也就不能为空。如果类的成员函数中没有对this指针的实际解引用,即便给this传空指针也不会出现问题。

如下程序会正常执行:

C++ 类和对象(一)类、访问限定符、this指针,C++,开发语言,c++

  p->Print()或(*p).Print()好像是对空指针p进行了解引用,实际上它调用Print()函数时会直接把p传给this,因为实参&(*p)和p是相同的。这种情况在实际中可能很少出现,但它是可行的。

如下程序就会运行崩溃:

C++ 类和对象(一)类、访问限定符、this指针,C++,开发语言,c++

  因为Print()函数内对成员变量进行操作,访问_a需要对this指针进行解引用,this->_a,对空指针解引用引起运行崩溃。

5.3 代码规范

1.this指针为何失灵?

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;
};

C++ 类和对象(一)类、访问限定符、this指针,C++,开发语言,c++

 执行以上程序,输出的却是随机值,说明对象d1调用了Init()函数但是d1的成员变量并没有初始化,这是为什么呢?

其原因是函数Init()内的year,month,day变量都是局部变量(函数形参),比如year = year,我们期望左边的year是类的成员变量year,右边是函数形参year,事实上左边的year也是函数的形参,因为year是存在的局部变量,函数内的year自然都优先与它对应,编译器不会“智能”地对左边的变量使用this->访问,它就不会对应类的成员变量。以上操作如同定义一个变量int a;,再赋值变量给它自己 a = a;

C++ 类和对象(一)类、访问限定符、this指针,C++,开发语言,c++

 因此要实现我们的期望,就有两种方法:显式使用this指针或改变变量名。

2.显式使用this指针

通过显式使用this指针,将左边的变量设为类的成员变量,即:

void Init(int year, int month, int day)
    {
        this->year = year;
        this->month = month;
        this->day = day;
    }

3.成员变量书写规范

将类成员函数的参数与类成员变量书写不同就能避免this指针失灵的问题。常见的代码书写规范是在类的成员变量前或后加_,即:

void Init(int year, int month, int day)
    {
        _year = year;
        _month = month;
        _day = day;
    }

private:
    int _year;
    int _month;
    int _day;

如果要在函数内使用全局变量,其参数也不能和全局变量重名,否则会将全局的名字隐藏,因此规范的变量命名是解决一些问题的通用方法,一般不使用第一种方法(显示使用this指针)。

C++ 类和对象(一)类、访问限定符、this指针,C++,开发语言,c++

如果本文内容对你有帮助,可以点赞收藏,感谢支持,期待你的关注。

下篇预告:C++ 类和对象(二)构造函数、析构函数、拷贝构造函数文章来源地址https://www.toymoban.com/news/detail-693706.html

到了这里,关于C++ 类和对象(一)类、访问限定符、this指针的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++】类与对象【定义、访问限定符、this指针】

      🌈个人主页: 秦jh__https://blog.csdn.net/qinjh_?spm=1010.2135.3001.5343 🔥 系列专栏: http://t.csdnimg.cn/eCa5z   目录 面向过程和面向对象初步认识  类的引入 类的定义 成员变量命名规则的建议: 类的访问限定符及封装 访问限定符  封装 类的实例化 类对象模型 类对象的存储方式 计

    2024年02月21日
    浏览(33)
  • 【是C++,不是C艹】 类与对象 | 认识面向对象 | 访问限定符 | 封装 | this指针

    💞💞 欢迎来到 Claffic 的博客 💞💞  👉  专栏: 《是C++,不是C艹》👈 前言: 在C++入门之后,就要进入C++的第一个核心:类与对象,这期带大家认识认识面向对象编程,访问限定符,封装以及 this 指针。 注: 你最好是学完了C语言,并学过一些初阶的数据结构。 (没有目

    2024年02月07日
    浏览(29)
  • C++初阶类与对象(一):学习类与对象、访问限定符、封装、this指针

    入门知识已经梳理完毕了,接下来就进入到面型对象的部分学习了 C语言典型的 面向过程 的,关注的是过程,分析出求解问题的步骤,通过函数调用 逐步解决 问题 C++是典型的基于 面向对象 的,关注的是对象,将一件事情 拆分成不同的对象 ,靠对象之间的交互完成。 将大

    2024年01月19日
    浏览(23)
  • C++类和对象-C++对象模型和this指针->成员变量和成员函数分开存储、this指针概念、空指针访问成员函数、const修饰成员函数

    #includeiostream using namespace std; //成员变量 和 成员函数 分开储存的 class Person { public:     Person() {         mA = 0;     }     //非静态成员变量占对象空间     int mA;     //静态成员变量不占对象空间     static int mB;     //函数也不占对象空间,所有函数共享一个函数实例

    2024年02月20日
    浏览(33)
  • 【c++】类和对象(二)this指针

    🔥 个人主页 :Quitecoder 🔥 专栏 :c++笔记仓 朋友们大家好,本节内容来到类和对象第二篇,本篇文章会带领大家了解 this指针 首先我们定义一个日期类date: 我们来思考这么一个问题: Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,也就是说,d

    2024年04月11日
    浏览(60)
  • 【C++】:类和对象(上)+ this指针

    【本节目标】 1.面向过程和面向对象初步认识 2.类的引入 3.类的定义 4.类的访问限定符及封装 5.类的作用域 6.类的实例化 7.类的对象大小的计算 8.类成员函数的this指针 C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题 C++是基于面向对象

    2024年02月08日
    浏览(27)
  • C++:类和对象(上)---初步认识类和this指针

    C语言是一门面向过程的语言关注的是过程,确认一个问题求解的步骤,再一步一步对它进行解决 C++是一门基于面向对象的语言,它更关注的是对象,将一个事情分成不同的对象,再用对象完成问题的解决 在C语言中有结构体,但结构体中只能定义变量,而在C++中还可以定义函

    2024年02月16日
    浏览(25)
  • 【C++】类和对象详解(类的使用,this指针)

    提示:这里可以添加本文要记录的大概内容: 在计算机编程领域,程序设计的方法论不断演化,从最初的面向过程到如今更为强大而灵活的面向对象。本文将深入探讨C++中关于类和对象的概念,为读者提供对面向对象编程的深刻理解。 提示:以下是本篇文章正文内容,下面

    2024年02月02日
    浏览(25)
  • 【C++深入浅出】类和对象上篇(类的基础、类的模型以及this指针)

    目录 一. 前言  二. 面向对象与面向过程         2.1 面向过程         2.2 面向对象 三. 类的基础知识 3.1 类的引入 3.2 类的定义 3.3 成员变量的命名规则 3.4 封装 3.5 类的访问限定符 3.6 类的作用域 3.7 类的实例化 四. 类的对象模型 4.1 类对象的大小 4.2 类对象的存储方式 4.3 空

    2024年02月10日
    浏览(35)
  • 【C++成长记】C++入门 | 类和对象(上) |类的作用域、类的实例化、类的对象大小的计算、类成员函数的this指针

    🐌博主主页:🐌​倔强的大蜗牛🐌​ 📚专栏分类:C++ ❤️感谢大家点赞👍收藏⭐评论✍️ 目录 一、类的作用域  二、类的实例化 三、类对象模型  四、this指针 1、this指针的引出  2 this指针的特性 类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定

    2024年04月15日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包