详解C++类&对象(上篇),带你走进C++

这篇具有很好参考价值的文章主要介绍了详解C++类&对象(上篇),带你走进C++。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一,面向对象&面向过程的认识(简单了解即可,逐步认识)

二, 类

2.1 类的引入 

2.2 类的定义

1. struct 

2. class 

类的两种定义方式:

2.3 封装&类的访问限定符 

1. 封装概念

2. 类的访问限定符 

2. 4 类的作用域

2. 5 类对象模型

1. 计算类大小

2. 类对象的存储方式

2.6  结构体内存对齐规则

2. 7  this指针

1. this指针特性

2. this指针面试题

结语


一,面向对象&面向过程的认识(简单了解即可,逐步认识)

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

C++是 基于面向对象的, 关注的是 对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。(C++也可以是面向过程&面向对象混合编写)。

 二, 类

2.1 类的引入 

    C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。
比如:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;

struct man
{
	char _name[10];
	int _age;

	void manitin(const char* name, int age) // 文件是cPP时不会报错,C文件会报错
	{
	}
};

int main()
{
  man z;  // 在C++自定义一个类,形成一个新的类型,同时也是类名。
  return 0;
}

2.2 类的定义

1. struct 

// C中结构体
struct MyStruct 
{
	int a;
	int b;
	// 函数无法写入
};

// C++为了兼容C,C模式写法在C++编译器下不会报错,同时
// C++将C升级为了类,让函数可以存在于类中。
struct man
{
	int a;
	int b;
	void func(int a, int b)
	{
		;
	}
};

2. class 

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

虽然有C的struct,但C++跟普遍使用class,这个后边会讲解。 嘎嘎

类的两种定义方式:

1. 声明和定义全部放在类体中,需注意:成员 函数如果 在类中定义,编译器 可能(代码比较少)可能将其当成 内联函数处理。  

2. 类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::函数名( namespace命名空间,也是如此,空间名::成员名)——————(当我们完成大项目时,更推荐这种,声明与函数定义文件分离,结构更清晰)

详解C++类&对象(上篇),带你走进C++

2.3 封装&类的访问限定符 

1. 封装概念

面向对象的三大特性:封装、继承、多态。 

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

就像一部电脑,外面被金属壳封装,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可

在C++语言中实现封装,可以 通过类将数据以及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用
    而电脑封装需要壳子,那么代码封装就有了类的的访问限定符。

2. 类的访问限定符 

 详解C++类&对象(上篇),带你走进C++

【访问限定符说明】
1. public修饰的成员在类外可以直接被访问。
2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)。
3. 访问权限 作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止 ,如果后面没有访问限定符,作用域就到 } 即类结束。
4. class的默认访问权限为private,struct为public(因为struct要兼容C)——这里我们可以看出C语言是比较自由的,想插入就插入

基本用法如下:

class man  // 默认private
{
private:  // 这一句可以不写——不允许类外部直接访问
	int a;
	int b;

public:   // 从这里开始允许类外部直接访问
	void func(int a, int b)
	{
		cout << a + b << endl;
	}
};

int main()
{
	man k;
	k.func(1, 2);
	//k.a; // 报错:不可访问
	return 0;
}
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别。

2. 4 类的作用域

    类定义了一个新的作用域,类的所有成员都在类的作用域中 。在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。
class man  // 默认private
{
private:  // 这一句可以不写——不允许类外部直接访问
	int a;
	int b;

public:   // 从这里开始允许类外部直接访问
	void func(int a, int b);
};

void man::func(int a, int b)
{
	cout << a + b << endl;
}

2. 5 类对象模型

1. 计算类大小

class man
{
	int age;
public:
	void func()
	{
		;
	}
};
class A
{
public:
	void A1()
	{
		;
	}
};
int main()
{
	cout << sizeof(man) << endl;  // 4字节,可见类成员函数并不存在于类中
	cout << sizeof(A) << endl;    // 没有成员变量的类,给1个字节,表示存在这个类对象。
	return 0;
}

2. 类对象的存储方式

详解C++类&对象(上篇),带你走进C++

 我们来测试下面代码,看看我们的VS2019的编译器是否是这样的方式?

class man
{
	int age;
public:
	void func()
	{
		;
	}
};

int main()
{
	man a;
	man b;
	man c;
	a.func();
	b.func();
	c.func();
	return 0;

详解C++类&对象(上篇),带你走进C++ 然后我们查看反汇编。

 详解C++类&对象(上篇),带你走进C++

我们会发现三个实例,调用的函数是同一个函数

这里我们直接进行解释吧,在编译时期,根据函数名就找到类成员函数所在的公共代码区地址,不用等到链接时期查找填充地址。

这里有一个代码验证上面结论,如下:

class man
{
	int age;
public:
	void func()
	{
		;
	}
};

int main()
{
	man* k = nullptr;
	k->func();
	return 0;
}

 详解C++类&对象(上篇),带你走进C++

详解C++类&对象(上篇),带你走进C++  

 可见,在两种调试信息格式下结果,可见:

  • 1. 不同的类实例,他们所调用的类内部函数都是同一个且存储在公共代码区 。
  • 2. 类内部的函数可能是内联函数, 在编译时期,调用函数是直接展开。

总结: 类成员函数会有这两种情况 

详解C++类&对象(上篇),带你走进C++

2.6  结构体内存对齐规则

  • 1. 第一个成员在与结构体偏移量为0的地址处。
  • 2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 (注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。VS中默认的对齐数为8)
  • 3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
  • 4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
  • 如果还是不怎么了解,请查看这篇 详解C语言中结构体,枚举,联合体易错点补充_花果山~~程序猿的博客-CSDN博客

 2. 7  this指针

        我们看下面代码:

class man
{
	int _age;
	int _tall;

public:
	void manInit(int age, int tall)
	{
		_age = age;
		_tall = tall;
	}
};

int main()
{
	man li;
	man ikun;

	li.manInit(20, 165);
	ikun.manInit(25, 180);
	return 0;
}

我们知道同一个类函数,其的代码放在公共代码区, 我们对li进行初始化,然后对ikun进行初始化,都是相同的一个函数都是_age = age;
        _tall = tall;不禁会想,ikun的初始化会不会覆盖li的数据呢??

的确这么低级的错误,科学家们想到了this值指针,C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏 的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成

 补全后就长这样,但会报错:

class man
{
	int _age;
	int _tall;

public:
	void manInit(man* const this ,int age, int tall) // 编译器会自动添加一个不可修改指向的this指针,不允许人为添加
		                                             // 这样就解决了找不到对象的问题。
	{
		cout << this << endl;  // 无法修改但可以读
		this->_age = age;      // 自动隐式添加
		this->_tall = tall;    // 自动隐式添加,这里只是人为显示
	}
};

int main()
{
	man li;
	man ikun;

	li.manInit(&li ,20, 165);
	ikun.manInit(&ikun, 25, 180);
	return 0;
}

1. this指针特性

  • this指针的类型:类类型* const,即成员函数中,不能给this指针赋值(不能对this指针更改指向)。
  • 只能在“成员函数”的内部使用。
  • this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
  • this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。(也有可能是通过栈)

2. this指针面试题

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:
	void Print()
	{
		cout << "Print()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->Print();
	return 0;
}

 结果是C.  正常运行。 解析:这个同前面题类似,print()是类成员函数,且代码短小,被当做内联函数处理,在编译时期就将调用处替换,并且未对p解引用。

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{ 
public:
    void PrintA() 
   {
        cout<<_a<<endl;
   }
private:
 int _a;
};
int main()
{
    A* p = nullptr;
    p->PrintA();
    return 0;
}

 结果是B.运行崩溃。 解析:print()是类成员函数,被当做内联函数处理,在编译时期就将调用处替换,同时传nullptr给this指针,后面对this(nullptr)进行解引用因此崩溃。

结语

本小节就到这里了,感谢小伙伴的浏览,如果有什么建议,欢迎在评论区评论,如果给小伙伴带来一些收获请留下你的小赞,你的点赞和关注将会成为博主创作的动力。文章来源地址https://www.toymoban.com/news/detail-448110.html

到了这里,关于详解C++类&对象(上篇),带你走进C++的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • C++ 基础知识 五 ( 来看来看 面向对象的继承 上篇 )

    C++ 继承是指派生类(子类)从基类(父类)继承属性和行为的过程。我们可以创建一个新的类,该类可以继承另一个类的数据属性和方法。 在上述代码中,我们定义了一个父类 Person 与一个子类 Student。Student 类继承了 Person 类的属性和方法,包括 name、age、gender 和 eat() 函数

    2024年02月03日
    浏览(96)
  • 【Spring】一文带你吃透AOP面向切面编程技术(上篇)

    个人主页: 几分醉意的CSDN博客_传送门 什么是AOP? AOP(Aspect Orient Programming):面向切面编程 Aspect:表示切面,给业务方法增加的功能,叫做切面。切面一般都是非业务功能,而且切面功能一般都是可以复用的。例如日志功能,事务功能,权限检查,参数检查,统计信息等等

    2024年01月16日
    浏览(65)
  • 面向对象三大特性之一——継承(上篇)

    目录 前文 一.什么是継承? 1.1 継承的定义 1.2 継承的格式 1.2.1 継承的使用格式 1.2.2 継承关系和访问限定符 二,基类和派生类对象复制转换 三,継承中的作用域 四,派生类/子类中的默认成员函数 六,継承与友元  六,継承与静态成员 总结 本篇文章主要是详解面向对象三大

    2024年02月03日
    浏览(42)
  • 【C++】面向对象---多态(万字详解)

           🔥🔥 欢迎来到小林的博客!!       🛰️博客主页:✈️小林爱敲代码       🛰️文章专栏:✈️小林的C++之路       🛰️欢迎关注:👍点赞🙌收藏✍️留言       今天给大家讲解多态,多态是面向对象的一个重要内容。也非

    2024年02月01日
    浏览(40)
  • 【Go 基础篇】走进Go语言的面向对象编程世界

    欢迎各位编程爱好者们!今天我们将进入Go语言的面向对象编程(OOP)世界,一窥这门语言如何运用OOP思想来组织和构建程序。无论你是初学者还是有一些经验的开发者,本文都将为你揭示Go语言中的OOP特性、方法和最佳实践。 面向对象编程是一种程序设计范式,它以对象为

    2024年02月10日
    浏览(54)
  • 【C++ • STL】一文带你走进string

    ヾ(๑╹◡╹)ノ\\\" 人总要为过去的懒惰而付出代价 ヾ(๑╹◡╹)ノ\\\" STL (standard template libaray- 标准模板库 ):是C++标准库的 重要组成部分 ,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。 STL六大组件 开源的:linux、git、STL、mysql、安卓……【开源会发

    2024年02月09日
    浏览(47)
  • 【C++杂货铺】一文带你走进RBTree

    红黑树是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是 Red 或 Black。通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,这句话换个意思就是:红黑树中最长路径不超过最短路径的 2 倍

    2024年02月08日
    浏览(55)
  • 一文带你入门C++类和对象【十万字详解,一篇足够了】

    本文字数较多,建议电脑端访问。不多废话,正文开始 从本文开始,我们就要正式来学习C++中的类和对象了,本文我将带你一步步 从C语言的结构体 struct 到C++的类 class ,真正搞懂有关C++的 面向对象的三大特征之一 —— 封装 作为读者,可能你正在学习C语言,亦或者已经开

    2024年02月05日
    浏览(47)
  • 【C++】类和对象(上篇)

    🚩 C语言 是 面向过程 的, 关注 的是 过程 ,分析出求解问题的步骤,通过函数调用逐步解决问题 🚩 C++ 是基于 面向对象 的, 关注 的是 对象 ,将一件事情拆分成不同的对象,靠对象之间的交互完成 🌰 比如: C语言结构体中只能定义变量, 在C++中,结构体内不仅可以定

    2024年01月22日
    浏览(39)
  • 【C++】类和对象(上篇)

    目录 一、类的引入 二、类的定义 三、类的访问限定符及封装   1、访问限定符   2、封装 四、类的作用域 五、类的实例化 六、类对象模型   1、计算类对象的大小   2、类对象的存储方式   3、结构体/类内对齐规则 七、this 指针   1、this 指针的引出   2、this 指针的特性 首

    2024年02月09日
    浏览(73)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包