详解C++类对象(上篇)——超详细

news2024/11/20 10:29:57

目录

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

二, 类

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命名空间,也是如此,空间名::成员名)——————(当我们完成大项目时,更推荐这种,声明与函数定义文件分离,结构更清晰)

2.3 封装&类的访问限定符 

1. 封装概念

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

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

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

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

2. 类的访问限定符 

 

【访问限定符说明】
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. 类对象的存储方式

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

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

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

 然后我们查看反汇编。

 

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

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

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

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

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

 

  

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

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

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指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过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)进行解引用因此崩溃。

结语

本小节就到这里了,感谢小伙伴的浏览,如果有什么建议,欢迎在评论区评论,如果给小伙伴带来一些收获请留下你的小赞,你的点赞和关注将会成为博主创作的动力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/495559.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

低代码如何不写代码创建表单和维护表单

工作表新建与修改 新建工作表的流程包含 新建工作表/编辑公祖表为工作表添加字段&#xff0c;例如“员工档案”表中有姓名、性别、年龄等字段为字段设置属性工作表布局工作表预览、保存、关闭 1、新建工作表/修改工作表 新建工作表 修改工作表 2、为工作表添加字段 添加字段 左…

关于C语言的一些杂记2

文章目录 sizeof运算符内容关于基本概念的问题关于一些语句的理解和分号的注意字符的理解关于输出格式的扩展 本文内容摘自C技能树一些优秀的博主 sizeof运算符内容 关于基本概念的问题 sizeof是C语言的关键字&#xff0c;它用来计算变量&#xff08;或数据类型&#xff09;在…

2.Hive创建数据库

1.数据库操作 1.1 创建数据库 create database test comment Just for test location /abcd with dbproperties(aaabbb); comment后面指的是注释&#xff1b;location后面是数据库存放路径&#xff1b;dbproperties代表了数据库的属性 ps.避免要创建的数据库已经存在错误&…

Vue最新状态管理工具Pinia——Pinia的安装与使用

Pinia从了解到实际运用——pinia的安装与使用 知识回调&#xff08;不懂就看这儿&#xff01;&#xff09;场景复现一、环境搭建1.创建项目2.安装pinia 二、基本使用1.创建pinia示例并挂载2.基本使用访问state使用getters使用actions 3.详细示例&#xff08;详细注解&#xff0…

【23】核心易中期刊推荐——视觉/图像感知与识别人工智能算法及应用​​​​​​​

🚀🚀🚀NEW!!!核心易中期刊推荐栏目来啦 ~ 📚🍀 核心期刊在国内的应用范围非常广,核心期刊发表论文是国内很多作者晋升的硬性要求,并且在国内属于顶尖论文发表,具有很高的学术价值。在中文核心目录体系中,权威代表有CSSCI、CSCD和北大核心。其中,中文期刊的数…

2023年盐城工学院五年一贯制专转本旅游学概论考试大纲

2023年盐城工学院五年一贯制专转本旅游学概论考试大纲 一、考核对象 本课程的考核对象是五年一贯制高职专升本酒店管理专业考生。 二、考核方式 本课程考核采用闭卷考试的方式。 三、考核要求 掌握旅游学的基本原理&#xff0c;掌握旅游学的核心概念&#xff0c;具备旅游…

Android性能监控:主循环性能统计LooperStatsService详解

作者&#xff1a;飞起来_飞过来 简介 在Android性能监控和优化领域&#xff0c;一个会影响App性能表现的因素与Handler Message Looper机制有关。当Looper里面的Message处理不及时、或数量太多占用过多处理时间时&#xff0c;可能会出现卡顿感&#xff0c;并且不容易定位到卡顿…

WoShop多商户进口出口跨境电商uniapp商城源码

源码介绍&#xff1a;WoShop多商户跨境电商商城系统将传统的分销、积分、拼团等传统销售模式和直播带货、短视频带货等新型电商营销完美融为一体&#xff0c;专注技术&#xff0c;支持二次开发&#xff0c;专为用户、技术商提供跨境电商技术解决方案。 WoShop跨境电商源码产品…

网络弹性基础知识和实践

什么是网络弹性 弹性是网络处理中断并继续以可接受的标准向用户提供服务的能力。网络运营可能会受到配置错误、断电或操作员错误等问题的威胁。当这种可能性发生时&#xff0c;最终用户无法访问网络&#xff0c;从而对组织产生负面影响。高度弹性的网络可以通过在网络运行中断…

chatgpt官网拒绝访问怎么处理-chatGPT入口正确打开方式

chatgpt官网拒绝访问的原因有哪些 OpenAI是一家人工智能技术公司&#xff0c;其官网是OpenAI最重要的宣传与交流平台之一。但是&#xff0c;有时访问OpenAI官网可能会受到限制或拒绝访问。以下是可能导致OpenAI官网拒绝访问的几个常见原因&#xff1a; IP地址被封锁: OpenAI网…

【Python】只需2行代码,轻松将PDF转换成Word(含示范案例)

文章目录 一、前期准备二、pdf2docx功能三、限制四、案例 一、前期准备 可将 PDF 转换成 docx 文件的 Python 库。该项目通过 PyMuPDF 库提取 PDF 文件中的数据&#xff0c;然后采用 python-docx 库解析内容的布局、段落、图片、表格等&#xff0c;最后自动生成 docx 文件。 …

LFU缓存结构算法

设计LFU缓存结构 LFU&#xff1a;最近最少频率使用 基本思想&#xff1a; 当缓存满时&#xff0c;加入新数据&#xff0c;淘汰缓存中使用次数最少的key&#xff0c;当使用次数最少的key有多个&#xff0c;删除最早调用的key。 定义节点的数据结构 class Node{//使用频率int …

从零开始学习Linux运维,成为IT领域翘楚(八)

文章目录 &#x1f525;Linux进程管理&#x1f525;ps&#x1f525;top&#x1f525;htop &#x1f525;Linux进程管理 &#x1f525;ps 查看系统中所有进程 语法&#xff1a; ps [options] [--help]参数&#xff1a; &#x1f41f; -a 显示所有进程&#xff08;包括其他用…

Windows Server 安装docker

在windows 10 或windows 11 上使用docker&#xff0c;可以直接在docker 官网下载docker desktop安装即可。 但在windows server上则无法支持docker desktop&#xff0c;此时可通过如下方式安装&#xff1a; 以 管理员权限运行Power Shell&#xff0c;然后执行&#xff1a; 安装…

微软骚操作恶心Win10用户,上网得先看广告

IE 浏览器在几个月前被彻底禁用&#xff0c;预装了快30年的老古董也确实到了退役的时候。 而微软也早有准备&#xff0c;2015年随着 Win10 发布推出了 Microsoft Edge 浏览器。 2020年迁移到 Chromium 内核让其成为了主流浏览器之一。 和 Chromium 系其他浏览器一样支持扩展插…

【计算机视觉 | 自然语言处理】BLIP:统一视觉—语言理解和生成任务(论文讲解)

文章目录 一、前言二、试玩效果三、研究背景四、模型结构五、Pre-training objectives六、CapFilt架构七、Experiment八、结论 一、前言 今天我们要介绍的论文是 BLIP&#xff0c;论文全名为 Bootstrapping Language-Image Pre-training for Unified Vision-Language Understa…

Node.js 的安装

node.js 通用的安装方式&#xff08;单版本&#xff09; Node.js 可以用不同的方式进行安装。 第一种&#xff0c;可以在官网中&#xff0c;根据自己的操作系统&#xff0c;选择对应的安装包。 打开官网网址&#xff08;Download | Node.js&#xff09; 第二种&#xff0c;就…

php+vue网盘系统的设计与实现

该网盘系统的开发和设计根据用户的实际情况出发&#xff0c;对系统的需求进行了详细的分析&#xff0c;然后进行系统的整体设计&#xff0c;最后通过测试使得系统设计的更加完整&#xff0c;可以实现系统中所有的功能&#xff0c;在开始编写论文之前亲自到图书馆借阅php书籍&am…

吉时利Keithley6430/6485/6487皮安表测试软件NS-SourceMeter

软件概述 NS-SourceMeter皮安表上位机软件用于实现吉时利皮安表的上位机控制功能&#xff0c;通过在软件上的相应操作&#xff0c;控制皮安表进行配置或者测量&#xff0c;同时可以对测量的数据和图形进行保存。NS-SourceMeter皮安表软件由计算机和皮安表组成&#xff0c;通过计…

026 - C++ 可见性

本期我们讨论 C 的可见性。 可见性是一个属于面向对象编程的概念&#xff0c;它指的是类的某些成员或方法有多可见。 我说的可见性是指&#xff0c;谁能看见它们&#xff0c;谁能调用它们&#xff0c;谁能使用它们等这些内容。 可见性是对程序实际运行方式完全没有影响的东西…