类和对象(上)

一、 类

1.1 类的格式

cpp 复制代码
class 类的名字
{
   成员变量;
   成员函数;     
};
  • 类里面将数据属性和实现方法包装在一个类中,这也是C++中封装特性的体现。
  • 类中包含成员变量和成员函数。在类中的成员函数被认为自动具有内联属性。
  • 类既可以是class型的,也可以是struct 型的。
  • 为了区分成员变量,通常在成员变量名前加 _ 。

1.2 访问限定符

访问限定符包括public、private、protected三种。

  • 在class中,class默认为private属性;而struct默认具有public属性。
  • 在class中可以拥有private和public两种属性。通常将成员函数设置为public,成员变量为private,为了防止成员变量被乱修改。
  • 访问限定符的作用域:从出现一个访问限定符开始,到另外一个访问限定符出现为止。
  • private和protected为私有,类外不可以使用类内可以访问;public为公开,可以在类外访问,但是需要注意用域作用访问限定符::或解引用操作符**.** 、 ->。

使用: :场景:

  1. 类外进行实现类内成员函数。
  2. 调用类内静态成员(变量/函数)。
  3. 子类和父类具有同名函数,子类强行调用父类中的函数。
cpp 复制代码
#include <iostream>
using namespace std;
class Base
{
public:
	static int a ;
	int b;
	static void show()
	{
		cout << "show()" << endl;
	}
	void show2();
};
void Base::show2()
{
	cout << "show2" << endl;
}
//先进行声明。
int Base::a = 10;

int main()
{
	Base base;
	
	//静态属于全局的,不需要先创建一个对象
	Base::a = 20;
	cout << Base::a << endl;
	Base::show();

    base.show2();
	return 0;
}

使用接引用操作符:针对于普通成员和函数。(但前提是public)

1.3 类域

类域就是类的作用域。类所有成员变量和函数都在这个作用域中。

类域影响的是编译查找规则。如果函数不在类内的话,函数被认为是全局的,如果找不到函数声明和定义,就会编译报错。如果函数是成员函数,在当前域内找不到成员,就会去类域内找,如果还找不见,就会编译报错。

二、实例化

2.1 实例化

  • 实例化其实很简单,将类看成一个抽象的模型,通过模型生成的一个个鲜活的不同个体(对象),就是实例化。
  • 类内的成员变量并没有内存空间的分配,只是声明。当类实例化出对象时,成员变量被分配内存空间。但是需要注意的是:成员函数并不会被分配到类内内存空间中,它存在于代码段中。
  • 类可以实例化出好多对象。

2.2 对象大小

我们说struct也是类,那么由它实例化出的对象我们是依靠内存对齐规则计算结构体大小。同样计算class类的内存大小也是依靠内存对齐规则计算。

内存对齐规则:

  1. 求类内每个成员的数据类型大小与默认对齐数的最小值(VS默认对齐数为8),求出各自对齐数。
  2. 第一个成员位于偏移量为0地址处,其他成员位于各自对齐数的整数倍处。
  3. 整体大小为最大对齐数的整数倍。

计算:

cpp 复制代码
include<iostream>
using namespace std;
// 计算⼀下A/B/C实例化的对象是多⼤?
class A
{
public:
    void Print()
    {
       cout << _ch << endl;
    }
private:      //数据类型大小      默认对齐数       对齐数     位置
    char _ch;       1               8              1         0
    int _i;         4               8              4        4-7
              //最大对齐数:4   类的大小:8
};

当类内无成员变量时,类的大小为1字节,作为占位。


三、 this指针

在调用成员函数时,函数体内并没有不同对象之间的区分,调用函数时,不知道到底是哪个对象,这是就需要this指针来解决。

  • 在编译时,调用函数时,函数有一个隐形参数来接收对象的地址,这就是用this指针。
  • 成员函数体内访问成员变量就是通过this指针来进行访问。
  • 函数的实参和形参中不需要加this指针这一参数,编译器会加。在成员函数体内可以显示使用this指针。
cpp 复制代码
#include <iostream>
using namespace std;
class Date
{
public:
	void InitDate(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
		print_Date(year, month, day);
	}
	void print_Date(int year, int month, int day)
	{
		cout << year << "-" << month << "-" << day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	d1.InitDate(2026, 7, 29);
	Date d2;
	d2.InitDate(2026, 7, 30);
	return 0;
}

练习:

cpp 复制代码
1.下⾯程序编译运⾏结果是()
A、编译报错 B、运⾏崩溃 C、正常运⾏
#include<iostream>
using namespace std;
class A
{
public:
    void Print()
    {
        cout << "A::Print()" << endl;
    }
private:
    int _a;
}
int main()
{
    A* p = nullptr;
    p->Print();
    return 0;
}
//在调用print()时,将nullptr给了this指针
//在print()函数体内,并没有解引用this,所以正常运行,不会报错。
//选C
2.this指针作为隐形参数,this指针存储在栈区。

四、C++中栈的实现

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

cpp 复制代码
#include <iostream>
#include <assert.h>
#include <stdlib.h>

typedef int STDataType;
using namespace std;
class Stack
{
	STDataType* _a;
	int size;
	int capacity;
public:
	void Init(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (nullptr == _a)
		{
			perror("malloc fail");
			exit(1);
		}
		
		capacity = n;
		size = 0;
	}
	void STPush(STDataType x)
	{
		assert(this);
		if (capacity == size)
		{
			capacity = 2 * capacity;
			STDataType* tmp = (STDataType*)realloc(_a, sizeof(STDataType) * capacity);
			if (nullptr == tmp)
			{
				perror("realloc fail");
				exit(1);
			}
			_a = tmp;
		}
		_a[size] = x;
		size++;
	}
	void STPop()
	{
		assert(this);
		assert(size > 0);
		size--;
	}
	int STSize()
	{
		assert(this);
		assert(size > 0);
		return size;
	}
	STDataType STTop()
	{
		assert(this);
		assert(size > 0);
		return _a[size - 1];
	}
	bool STIsEmpty()
	{
		assert(this);
		return size == 0;
	}
	void STDestroy()
	{
		free(_a);
		_a = nullptr;
		size = capacity = 0;
	}
};
int main()
{
	Stack st;
	st.Init();
	st.STPush(1);
	st.STPush(2);
	st.STPush(3);
	st.STPush(4);
	st.STPush(5);

	st.STPop();
	st.STSize();
	cout << st.STSize() << " " << st.STIsEmpty() << " " << st.STTop() << endl;
	return 0;
}
相关推荐
脉动数据行情15 分钟前
C# 实现德指 DAX 期货 WebSocket 实时行情监听
开发语言·websocket·c#
大圣编蚕31 分钟前
Java ByteArrayInputStream 详解:从入门到实战
java·开发语言·算法
菜鸟~noob23339 分钟前
【电子战】第02篇:能量检测器 vs. 相关检测器【含matlab代码】
开发语言·matlab
OpenAnolis小助手2 小时前
一句话看透 JVM,SysOM 诊断 Skill 新增 Java 应用诊断能力
java·开发语言·jvm·阿里云·操作系统控制台·sysom
小玮看世界2 小时前
[Python]OD算法在OD实际运用转化参考清单
开发语言·python·算法
ForteScarlet2 小时前
Kotlin 2.4.20 现已发布,新特性多不多?
android·java·开发语言·开源·kotlin·jetbrains
萧瑟余晖2 小时前
Java深入解析篇六十二之安全机制详解
java·开发语言
老赵的博客3 小时前
c++ QT之动态库加载问题
c++·qt
菜鸟~noob2333 小时前
【电子战】 第01篇:噪声、门限与虚警/检测概率(PFA/PD)【含matlab代码】
开发语言·matlab
奇牙coding1233 小时前
GPT-6-Astra API 接入教程:OpenRouter 路由配置 + Python/curl 示例 + 静默降级踩坑
开发语言·python·gpt·ai