【C++基础(五)】类和对象(上)

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:C++初阶之路⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习C++

🔝🔝


类和对象-上

  • [1. 前言](#1. 前言 "#1__15")
  • [2. 类的引入](#2. 类的引入 "#2__35")
  • [3. 类的定义](#3. 类的定义 "#3__72")
  • [4. 类的访问限定符](#4. 类的访问限定符 "#4__150")
  • [5. 类的实例化](#5. 类的实例化 "#5__220")
  • [6. 类对象模型](#6. 类对象模型 "#6__262")
    • [6.1 类对象的存储模式](#6.1 类对象的存储模式 "#61__310")
  • [7. this指针](#7. this指针 "#7_this_338")
    • [7.1 this指针的特性](#7.1 this指针的特性 "#71_this_382")
    • [7.2 this指针的用处](#7.2 this指针的用处 "#72_this_422")
  • [8. 总结以及拓展](#8. 总结以及拓展 "#8__466")

1. 前言

C语言是面向过程的语言
关注的是过程
而C++是面向对象的语言
关注的是对象

而类和对象就是面向对象的基础!

C++为了兼容C语言

保留了原先的玩法,并且增加了新的玩法

本章重点:

本篇文章着重讲解类的概念,基本特性
成员函数的性质,和最重要的this指针


2. 类的引入

C语言的结构体功能单一

只能定义成员变量,不能定义函数

而C++中新增了一个玩法:
可以定义成员函数

比如:

cpp 复制代码
struct NEO
{
	int a;
	char b[20];
	void test()//成员函数
	{
		cout<<"杭州电子科技大学"<< endl;
	}
	void push(char ch,int i)//成员函数
	{
		b[i] = ch;
	}
};

int main()
{
	NEO tmp;
	tmp.test();//会打印"杭州电子科技大学"
	tmp.push('a',1);//数组b下标为1的位置会被插入一个字符'a'
}

在C++中,C的结构体就是类
并且C++中更喜欢用class替代struct


3. 类的定义

cpp 复制代码
class className
{
	// 类体:由成员函数和成员变量组成
};   一定要注意后面的分号

类的定义与结构体类似
只不过将struct换成了class

类成员函数的两种定义方式:

  1. 声明和定义都放在类中:
cpp 复制代码
class people
{
	char* name;
	char* sex;
	int height;
	int age;
	void peoinfo()//打印此人的消息
	{
		cout<<name<<" "<<sex<<" "<<height<<" "<<age;
	}
};

这个类的成员函数的声明和定义都在类中

编译器就可能把此函数当作内联处理!
只要是在类中定义的函数都会被看作内联

当然这只是给编译器一建议
具体会不会内当作内联要看代码长度

  1. 类函数声明定义分开

一般说的声明和定义分开是指:
声明放在.h文件,定义放在.cpp文件

.h文件

cpp 复制代码
class people
{
	char* name;
	char* sex;
	int height;
	int age;
	void peoinfo()//打印此人的消息
};

.cpp文件(错误实例)

cpp 复制代码
void peoinfo()//打印此人的消息
	{
		cout<<name<<" "<<sex<<" "<<height<<" "<<age;
	}

注意:在另一个文件中,必须要加上类名::

否则系统不知道你是要新定义一个函数

还是要定义已经声明过的函数

正解:

cpp 复制代码
void people::peoinfo()//打印此人的消息
	{
		cout<<name<<" "<<sex<<" "<<height<<" "<<age;
	}

4. 类的访问限定符

首先介绍三个访问限定符:

访问限定符说明:

  1. public修饰的成员在类外
    可以直接被访问
  2. protected和private修饰的成员
    在类外不能直接被访问
  3. 访问权限作用域:
    从该访问限定符出现的位置开始直到
    下一个访问限定符出现时为止
  4. 如果后面没有访问限定符了
    作用域就一直到类结束
  5. class的默认访问权限为private
    struct为public(因为要兼容C)

举例说明:

cpp 复制代码
class NEO
{
public:
	void test1()
	{
		cout<<"haha";
	}

	void test2()
	{
		cout<<"hehe";
	}

private:
	int a;
	char b[20];
	double c;
}

int main()
{
	NEO tmp;
	tmp.test1();//正常运行
	tmp.a = 10;//运行报错
	tmp.c = 20;//运行报错
	return 0;
}

此类中,public和private
之间的成员是共有的,类外可以访问
private到类结束的成员是私有的
类外不能访问!

需要注意的点:

不管成员函数是共有还是私有
也不管成员变量是共有还是私有
成员函数都可以访问到成员变量!


5. 类的实例化

用类类型创建对象的过程,称为类的实例化

在实例化类对象之前,这个类并不占用内存

比如:

cpp 复制代码
class Person
{
public:
	void printper()
	{
		cout<<name;
	}
private:
	char* name;
};

int main()
{
	Person.name = "NEO";//编译报错,还没有实例化对象
	Person p1;
	return 0;
}

若没有实例化对象p1

这个class类是不会开辟空间的!

class类就像一个设计图纸一样
在按照这个图纸建设房子前
这块区域是没有空间占用的
实例化对象就像按照图纸修房子一样
会占用空间


6. 类对象模型

怎么计算一个class类的大小?

例如:下面这两个类:

cpp 复制代码
class A
{
	void PrintA()
	{
		cout << a << endl;
	}
	int a;
	char b;
};

class B
{
	int a;
	char b;
};

int main()
{
	printf("类A的大小: %d\n", sizeof(A));
	printf("类B的大小: %d\n", sizeof(B));
	return 0;
}

结论:

  1. 类中的成员函数不算在类的大小中
  2. 类的大小遵守结构体内存对齐规则
  3. 空类(没有成员变量)的大小是1字节

注:如果你不知道结构体内存对齐规则

请点击:结构体内存对齐规则


6.1 类对象的存储模式

为啥类中的成员函数不占空间?
那函数存储在什么位置?

带着这样的疑惑来看看类的存储模式:

  • 类成员变量存储在实例化对象中
  • 类成员函数存储在公共的代码段

可以用下面这张图来理解:

对类成员变量的解释:

由于每一个对象中的变量的值可能不同
所以成员变量存储在不同的对象中

对类成员函数的解释:

但是每个对象调用的函数是相同的
为了节省空间,将成员函数从对象中剥离
到公共代码段,不管实例化多少个对象
只要调用成员函数就会去代码段找!


7. this指针

先看以下的日期类:

cpp 复制代码
class Date
{ 
public:
	void Init(int year, int month, int day)
	{
 		_year = year;
	 	_month = month;
	    _day = day;
    }
private:
 	int _year;     // 年
	int _month;    // 月
	int _day;      // 日
};

int main()
{
	Date d1;
	d1.Init(2023,7,22);//初始化对象
	return 0;
}

看似Init只有三个参数

看似调用Init时只传了三个参数

但其实还有一个隐藏的指针this!

可以用下图理解this的位置:

并且在每一个成员变量之前
都有this指针解引用访问它:


7.1 this指针的特性

基本特性:

  1. this指针的类型:const 类类型 *
    即成员函数中,不能给this指针赋值
  2. 只能在"成员函数"的内部使用
  3. this指针不能我们显示去写
    也不能我们显示去传对象地址
  4. this指针存储在栈区,不存储在对象中

对特性的理解:

不能这样写代码:

cpp 复制代码
class A
{ 
void Init(A* this,int a)
{
	_a=a;
}
 int _a;
};

int main()
{
	A a1;
	a1(&a,10);
}

假如这样写代码,那么函数参数就有三个
系统还是会自动传this指针,会报错


7.2 this指针的用处

假设我们实例化了两个对象

分别是d1和d2

cpp 复制代码
class Date
{ 
public:
	void Init(int year, int month, int day)
	{
 		_year = year;
	 	_month = month;
	    _day = day;
    }
private:
 	int _year;     // 年
	int _month;    // 月
	int _day;      // 日
};

int main()
{
	Date d1;
	Date d2;
	d1.Init(2023,7,22);//初始化对象
	d2.Init(2023,7,23);
	return 0;
}

已知成员函数是放在公共代码段的
假如没有this指针存在
函数体又没有区别不同对象的手段

那么就会出现一个问题:
对象d1调用函数Init时,函数不知道是
哪一个对象调用了它,就无法区分对象

使用this指针将对象的地址传入函数中
函数体就可以区分不同对象了!


8. 总结以及拓展

本章是类和对象的入门篇
只介绍了类的解基本概念和特性
其中比较重要的是this指针
它还会陪伴我们很久!

基础不牢,地动山摇
类学不会,学C++就受罪

拓展: C++命名方式

C++又很多习惯的命名方式

这里介绍一个:驼峰法命名

  • 单词和单纯之间首字母大写
  • 函数名,类名首字母大写
  • 变量首字母小写,后面单词首字母大写
  • 成员变量的首字母前加下划线_

举例说明:

cpp 复制代码
class Date
{ 
public:
  void InitDate(int year, int month, int day)//initialize date
  {                                          //初始化日期,简写后,I和D要大写
    _year = year;
    _month = month;
    _day = day;
  }
  void PrintInfo()//printf information,简写后P和I要大写
  {
    cout <<_year<< "-" <<_month << "-"<< _day <<endl;
  }
private:
  int _year; //成员变量前面加_
  int _month;
  int _day;     
};

🔎 下期预告:类和对象(中) 🔍

相关推荐
2035去旅行4 小时前
bootcmd 详细讲解
linux·嵌入式·arm·soc
陈希1235 小时前
Linux 防火墙配置实战:firewalld、iptables 与云安全组
linux·运维·服务器
女神下凡5 小时前
芯参谋(95):嵌入式文件系统_开发指南
linux·服务器·arm开发·驱动开发·设计规范
且从容.9 小时前
Ubuntu安装flume
linux·ubuntu·flume
承渊政道9 小时前
Linux网络学习【Reactor反应堆模式】
linux·网络·学习·ubuntu·reactor
且从容.12 小时前
ubuntu安装flink
linux·ubuntu·flink
爱和冰阔落14 小时前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
程序员沉梦听雨14 小时前
WSL2的安装与使用
linux·wsl
微小的鱼14 小时前
Linux的渲染与显示系统链路
android·java·linux
lisanmengmeng14 小时前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器