一、 类
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为公开,可以在类外访问,但是需要注意用域作用访问限定符::或解引用操作符**.** 、 ->。
使用: :场景:
- 类外进行实现类内成员函数。
- 调用类内静态成员(变量/函数)。
- 子类和父类具有同名函数,子类强行调用父类中的函数。
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类的内存大小也是依靠内存对齐规则计算。
内存对齐规则:
- 求类内每个成员的数据类型大小与默认对齐数的最小值(VS默认对齐数为8),求出各自对齐数。
- 第一个成员位于偏移量为0地址处,其他成员位于各自对齐数的整数倍处。
- 整体大小为最大对齐数的整数倍。
计算:
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;
}