类和对象(上)

一、 类

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;
}
相关推荐
花生了什么事o1 小时前
synchronized 与 ReentrantLock:Java 锁机制原理与实现对比
java·开发语言
aramae1 小时前
C++ IO流完全指南:从C标准库到C++流式编程
服务器·c语言·开发语言·c++·后端
ZHOU_WUYI1 小时前
4. light wam 模型loss计算过程
开发语言·人工智能·python
_wyt0012 小时前
c++里的族谱:树
c++·
长不胖的路人甲2 小时前
Serial 串行、Parallel 并行、CMS 并发收集器
java·开发语言·jvm
@三十一Y2 小时前
C++:AVL树实现
c++
ShineWinsu3 小时前
对于Linux:传输层协议UDP原理的解析
linux·c++·面试·udp·协议·传输层·计算机系统
LingzhiPi3 小时前
零知派ESP32--AS5600磁吸旋钮音量控制器
c++·单片机·嵌入式硬件
麻瓜老宋3 小时前
AI开发C语言应用按步走,表达式计算器calc的第二十四步,结束开发,生成calc 用法指南
c语言·开发语言·atomcode