【C++入门】类和对象(一)

news2024/11/23 16:45:32

 

目录

前言

1. 面向对象和面向过程

 2. 类的引入

 3. 类的定义

 3.1 类的定义方法

4. 类的访问限定符和封装

 4.1 访问限定符 

4.2 封装

 5. 类的作用域

 6. 类的实例化

7.  类对象模型

 7.1 类对象的大小

8. this指针 


前言

     在初学C语言时,想必大家都听说过 “ 面向过程 ” 和 “ 面向对象 ”,C语言是面向过程的编程语言,而我们常用的C++,Java、python都是面向对象的编程语言,那什么面向过程,什么又是面向对象?它们有什么区别呢?那么今天我们就来了解一下C++中的类和对象。

在这里插入图片描述

1. 面向对象和面向过程

         C语言是面向过程的编程语言,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决。有人以洗衣服为例,进行了形象的比喻,把C语言实现一个功能比作洗衣服,那么它的过程如下边的流程一样:    

   

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

 可分为四个对象:人、衣服、洗衣机、洗衣液

 洗衣服整个过程是由四个对象交互完成。

 2. 类的引入

 在C语言中:

结构体中只能定义变量

 而在C++中:

结构体内不仅可以定义变量,也可以定义函数

 比如:

struct Data
{
	void Init(int year,int month,int day)//成员函数
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()//成员函数
	{
		cout << _year << _month << _day << endl;
	}
	int _year;
	int _month;
	int _day;
};

   C语言中的结构体也可以被称为类

 可以说是一个极简的类

 C++中兼容C语言struct所有用法

 C++ 中将struct升级成了类

C++更喜欢用class来代替

 3. 类的定义

class MyClass 
{
    // 类的成员和函数声明

};   //注意分号不能省略
  • class为定义类的关键字
  •  MyClass为类的名字
  •  { }中为类的主体
  •  类体中内容称为类的成员

 类中的变量称为类的属性(成员变量)

 类中的函数称为类的方法(成员函数 )

 3.1 类的定义方法

  •  声明定义都放在类里

 成员函数在类中定义:

class Data
{
public:
	void Print()
	{
		cout << _year << _month << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

 成员函数定义在类中,会被当作内联函数处理

 注意

  1. 成员函数默认直接在类中定义就是inline
  2. 长的函数最好声明和定义分离
  3. 短小的函数可以直接在类里定义
  •  声明与定义分离 
//Date.h

class Data
{
public:

	void Print();
	
private:
	int _year;
	int _month;
	int _day;
};

//Date.cpp

void Date::Print()
{
	cout << _year << _month << _day << endl;
}

命名建议:

 大家可能有疑惑,为什么我要在变量前加 “_” 

 比如:

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

在写一些初始化函数时,将值赋给类中的变量

 这样写容易分不清楚哪个是成员变量

为了便于区分,建议这样写:

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

4. 类的访问限定符和封装

 4.1 访问限定符 

 封装时不可能将所有的成员都让外部用户使用

访问限定

选择性的将其接口提供给外部的用户使用 

 限定符说明:

  • public修饰的成员在类外可以直接被访问
  • protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的) 
  • 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
  • 如果后面没有访问限定符,作用域就到 } 即类结束
  • class的默认访问权限为private,struct为public(因为struct要兼容C)

 C++中struct和class的区别是什么?

  1.  C++中struct可以当成结构体使用,还可以用来定义类
  2. struct定义的类默认访问权限是public,class定义的类默认访问权限是private

4.2 封装

 为了便于给外部用户使用于是就引入了封装的概念

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

 封装本质上是一种管理,让用户更方便使用类

 5. 类的作用域

 类的作用域体现在成员函数的声明和定义分离

在类的外边定义成员函数时需要指定域

//Date.h

class Data
{
public:

	void Print();
	
private:
	int _year;
	int _month;
	int _day;
};

//Date.cpp

void Date::Print()//Date::域作用限定,限定成员函数Print()属于类Date
{
	cout << _year << _month << _day << endl;
}

 6. 类的实例化

 类的实例化,就是创建对象的过程

 类是对对象的描述,并没有分配实际的空间

int main()
{
	Date.year=2023;//报错
	return 0;
}

 Date类没有实际存储空间

 类就像是设计图,可以通过图纸建造多个房子

  • 一个类可以实例化(创建)出多个对象
  • 实例化出的对象 占用实际的物理空间存储类成员变量

7.  类对象模型

 7.1 类对象的大小

class Data
{
public:
	void Print()
	{
		cout << _year << _month << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

类中既可以有成员变量,也可以有成员函数,要如何计算?

上述类的大小为12

在类的实例化中提到过:

实例化出的对象 占用实际的物理空间存储类成员变量

  •  成员变量存在对象中
  • 成员函数的地址不在对象中

 总结: 

 类大小计算和结构体大小计算相同(不考虑函数)

 结构体大小计算详细可见:从头开始:自定义类型入门指南(结构体、位段、枚举、联合)

  •  为了更有效的使用空间,成员函数使用的是一个独立的空间(公共代码区)
  •  不同对象调用相同成员函数,实际上调用的是同一个函数

 那空类或者说只有成员函数的类大小是多少


class A//大小1字节
{};

class B//大小1字节
{
public:
    void f2() {}//成员函数在独立的空间
};

 为什么是占一个字节?

  • 无成员变量的类,对象大小开一个字节,这个字节不存储有效数据
  •  标识定义的对象存在过

8. this指针 

 不同的对象调用同一函数,函数如何区分?

class Data
{
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(2023,10,24);
    Date d2(2022,10,24);
    
    d1.Print();//调用相同的print函数(没用参数)输出结果不同
    d2.Print();

	return 0;
}

为了便于区分,于是引入了this指针的概念。

  • C++中非静态的函数成员都有个隐藏的this指针
  • 指向当前对象(函数运行时调用该函数的对象)
  • 函数体中所有成员变量,都是通过该指针去访问
  • 用户不需要来传递,编译器自动完成
  •  this指针为*const类型(成员函数中,不能给this指针赋值)

 所以真实调用是这样的:

void Print(Date* this)
{
	cout << this->_year <<  this->_month <<  this->_day << endl;
}

虽然this指针在参数列表里没有显示,但是可以在类里显示使用

面试题:

 this指针存在哪里?

 this指针存在栈帧里(VS中,存到了寄存器ecx中)

 this指针可以为空吗?

 我们以下面的代码为例:

代码一:

class A
{

public:
	void Print()
	{
		cout << "Print()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->Print();//这里并不是传p的地址过去,传的是p
	return 0;
}

 代码一可以正常运行

为什么?

        前边提到,成员函数不在对象里边,所以找Print函数时并不需要通过A的指针来访问,并且Print函数内部也没有访问类的成员变量(没用使用this指针)。这里p的作用仅仅是说明Print函数是A里的成员函数,所以并不会访问到空地址。

代码二:

class A
{
public:
	void PrintA()
	{
		cout << _a << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->PrintA();
	return 0;
}

代码二在运行时会运行崩溃

代码一中也做了解释:

        成员函数不在对象里边找PrintA函数时并不需要通过A的指针来访问 ,但是在执行PrintA函数时使用了this指针访问成员变量,这里的this指针是空指针(无效地址),在访问时就会访问冲突,所以会造成运行崩溃(运行错误)。

由此我们可以总结出:

        this指针可以为空,但要看它是否访问成员变量,如果通过this指针访问了成员变量就会运行崩溃,如果没有访问那也可以正常运行。

         好了以上便是本期全部内容,希望对你有所帮助,最后感谢阅读!

         

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

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

相关文章

基于STC12C5A60S2系列1T 8051单片机EEPROM应用

基于STC12C5A60S2系列1T 8051单片机EEPROM应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍STC12C5A60S2系列1T 8051单片机EEPROM介绍基于STC12C5A60S2系列1T 8051单…

02 线性组合、张成的空间与基

线性组合、张成的空间与基 基向量缩放向量并相加给定向量张成的空间线性相关与线性无关空间的基 这是关于3Blue1Brown "线性代数的本质"的学习笔记。 基向量 当看到一对描述向量的数时&#xff0c;比如[3,-2]时&#xff0c;把这对数中的每个数&#xff08;坐标&…

Android性能优化--Perfetto用SQL性能分析

Android性能优化–Perfetto用SQL性能分析 文章目录 Android性能优化--Perfetto用SQL性能分析介绍Perfetto SQL 基础使用 Perfetto SQL 进行性能分析总结 本文首发地址 https://blog.csdn.net/CSqingchen/article/details/134167741 最新更新地址 https://gitee.com/chenjim/che…

Git从基础到实践

1.Git是用来做什么的&#xff1f; git就是一款版本控制软件&#xff0c;主要面向代码的管理。你可以理解为Git是一个代码的备份器&#xff0c;给你的每一次修改后的代码做个备份&#xff0c;防止丢失&#xff0c;这个是git最基本的功能。 其次,git不止备份,当你需要比对多…

隔离和非隔离电源的区别

一、电源隔离与非隔离 电源的隔离与非隔离&#xff0c;主要是针对开关电源而言&#xff0c;业内比较通用的看法是&#xff1a; 1、隔离电源&#xff1a;电源的输入回路和输出回路之间没有直接的电气连接&#xff0c;输入和输出之间是绝缘的高阻态&#xff0c;没有电流回路。 …

性格孤僻的人怎么改变自己?

性格孤僻&#xff0c;说的是寡言少语&#xff0c;不合群&#xff0c;不能与人保持正常关系、经常离群索居的心理状态。这里只是说性格&#xff0c;不涉及心理疾病&#xff0c;只说这是一种性格特征。性格孤僻的人不一定有心理疾病&#xff0c;但是长期的性格孤僻确实容易导致产…

VueI18n中英文切换 vue2.0

1: npm install --save vue-i18n8.0.0 &#xff08;版本不要高了&#xff0c;不然报错&#xff09; 2&#xff1a;创建相关文件 3&#xff1a;main.js文件配置 //i18n插件 import VueI18n from vue-i18n // element-ui多语言文件 import locale from element-ui/lib/locale;…

旋转图像[中等]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给定一个n n的二维矩阵matrix表示一个图像。请你将图像顺时针旋转90度。你必须在原地旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。 示例 1&#xff1a; 输入&#xff1a; matrix…

perl列表创建、追加、删除

简介 perl 列表追加元素 主要是通过push和unshift函数来实现。其中&#xff0c;push是追加到列表尾&#xff0c;unshift是追加到列表头。 perl列表删除元素 主要是通过pop和shift函数来实现。其中&#xff0c;pop是从列表尾删除一个元素&#xff0c; shift是从列表头删除一…

以配置的方式开关axios拦截器功能

前景提要&#xff1a; ts 简易封装 axios&#xff0c;统一 API 背景 axios 很多额外功能都是基于拦截器实现。有些功能想要全局使用&#xff0c;因此将拦截器注册在全局。比如重复请求过滤。但也有一小部分请求不希望进行过滤&#xff0c;比如并发上传文件。 因此希望可以在…

贰[2],OpenCV函数解析

1&#xff0c;imread&#xff1a;图片读取 CV_EXPORTS_W Mat imread( const String& filename, int flags IMREAD_COLOR );//参数1(filename)&#xff1a;文件地址 //参数2(flags):读取标志 注:ImreadModes&#xff0c;参数2(flags)枚举定义 enum ImreadModes { IMREAD…

SOEM源码解析——ec_init(初始化单网卡主站)

0 工具准备 1.SOEM-master-1.4.0源码1 ec_init总览 /** Initialise lib in single NIC mode:初始化库在单网卡模式* param[in] ifname Dev name, f.e. "eth0" 设备名* return >0 if OK* see ecx_init*/ int ec_init(const char * ifname) {return ecx_init(&…

构建高性能嵌入式系统的技术要求

目录 关键的技术要求 硬件设计 嵌入式操作系统&#xff08;Embedded Operating System&#xff09; 内存管理 电源管理 通信接口 实时性能 软件优化 安全性 关键的技术要求 硬件设计&#xff1a; 处理器选择&#xff1a; 选择适当的处理器架构&#xff0c;考虑性能、功…

点大商城V2版 2.5.2.1 全开源独立版 多小程序端+unipp安装教程

点大商城V2是一款采用全新界面设计支持多端覆盖的小程序应用&#xff0c;支持H5、微信公众号、微信小程序、头条小程序、支付宝小程序、百度小程序&#xff0c;本程序是点大商城V2独立版&#xff0c;包含全部插件&#xff0c;代码全开源&#xff0c;并且有VUE全端代码。分销&am…

MMDetection 系列(一): 初步入门配置文件

参考文档 不得不知的 MMDetection 学习路线(个人经验版) 轻松掌握 MMDetection 整体构建流程(一) 学习配置文件 MaskRCNN 配置文件的逻辑 整体来说&#xff0c;配置文件包含以下几个部分&#xff1a; 数据集和评测器配置模型配置训练和测试的配置优化相关配置钩子配置(TODO…

Web测试与APP测试详解

前言 单纯从功能测试的层面上来讲的话&#xff0c;App 测试、Web 测试在流程和功能测试上是没有区别的&#xff0c;但由于系统结构方面存在差异&#xff08;web 项目&#xff0c;b/s 架构&#xff1b;app 项目&#xff0c;c/s 结构&#xff09;在测试中还是有不同的侧重点内容…

使用opencv和dlib库(C++代码)实现人脸活体检测(眨眼、张嘴、摇头检测)

前言 本文章使用opencv和dlib库,使用C++代码实现了人脸活体检测,包括眨眼检测、张嘴检测以及摇头检测,可以对静态图片和活体进行有效区分。效果展示 Dlib库介绍 dlib是一个开源的C++机器学习库,它提供了一系列用于图像处理、人脸检测、人脸识别、物体检测、图像标注等功能的…

stable diffusion公司发布4款LLM大语言模型,为何大家都喜爱LLM?

stable diffusion模型是Stability AI开源的一个text-to-image的扩散模型&#xff0c;其模型在速度与质量上面有了质的突破&#xff0c;玩家们可以在自己消费级GPU上面来运行此模型&#xff0c;本模型基于CompVis 和 Runway 团队的Latent Diffusion Models。本期我们不介绍stabl…

口才不好可以做管理岗吗?

口才不好也可以选择管理岗位 口才是很重要的职场技能之一&#xff0c;但是并不代表没有口才就不能从事管理工作。管理岗位需要的不仅是口才&#xff0c;还包括组织能力、决策能力、问题解决能力等多种素质。下面我从以下几个方面来分析一下&#xff0c;口才不好的人也有可能选…

MySQL(8):聚合函数

聚合函数介绍 聚合函数&#xff1a; 对一组数据进行汇总的函数&#xff0c;输入的是一组数据的集合&#xff0c;输出的是单个值。 聚合函数类型&#xff1a;AVG(),SUM(),MAX(),MIN(),COUNT() AVG / SUM 只适用于数值类型的字段&#xff08;或变量&#xff09; SELECT AVG(…