类和对象定义
class 为类的关键字,其中类体中内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的⽅法或者成员函数。类中可以定义函数,变量等等。
C++对C语言中的 struct 也进行了升级,升级成了类,并且同时有保留了原来的用法。
要实现一个类,一定少不了访问限定符,C++⼀种实现封装的⽅式,⽤类将对象的属性与⽅法结合在⼀块,让对象更加完善,通过访问权限选择性的将其接⼝提供给外部的用户使⽤。其访问限定符有三个:
而 class 和 struct 定义的类唯一差别就是:class定义成员没有被访问限定符修饰时默认为private,struct默认为public。
⽤类类型在物理内存中创建对象的过程,称为类实例化出对象。
代码示例:
#include<iostream>
class Func
{
public:
// 成员函数 / 类的方法
int ADD(int a, int b)
{
return a + b;
}
//在类内声明,在类外实现
void Swap(int& a, int& b);
private:
// 成员变量 / 类的属性
int a;
double b;
char c;
};
// 在类外实现,要指定类域
void Func::Swap(int& a, int& b)
{
int tmp = a;
a = b;
b = tmp;
}
// C++兼容C中struct的⽤法
struct ListNodeC
{
struct ListNodeC* next;
int val;
};
// C++改进后的用法
struct ListNodeCPP
{
public:
void Init(int x)
{
next = nullptr;
val = x;
}
private:
ListNodeCPP* next;
int val;
};
int main()
{
// Func类实例化出对象fc
Func fc;
fc.ADD(1, 2);
// 设为外部不可见后,在类外访问不到a、b、c,此处会报错
// fc.a;
// C语言写法
struct ListNodeC nodeC;
// C++写法,显而易见C++写法更简便
ListNodeCPP nodeCPP;
return 0;
}
由上述代码也可以看到,类定义了⼀个新的作⽤域,类的所有成员都在类的作⽤域中,在类体外定义成员时,需要使⽤ :: 作用域操作符指明成员属于哪个类域。
隐含的this指针
看这段代码:
#include<iostream>
class Stack
{
public:
void Init(int n = 4)
{
a = (int*)malloc(sizeof(int) * 4);
capacity = 4;
top = 0;
}
void Push(int x)
{
if (top == capacity)
{
int newcapacity = 2 * capacity;
int* tmp = (int*)realloc(a, sizeof(int) * newcapacity);
a = tmp;
capacity = newcapacity;
}
a[top++] = x;
}
void Destroy()
{
free(a);
a = nullptr;//空指针
top = capacity = 0;
}
private:
int* a;
int top;
int capacity;
};
int main()
{
//Stack类实例化出对象st1、st2
Stack st1;
Stack st2;
st1.Init();
st2.Init();
st1.Destroy();
st2.Destroy();
return 0;
}
Stack 类中有 Init 与 Destroy 两个成员函数,函数体中没有关于不同对象的区分,那当d1调⽤ Init 与 Destroy 函数时,该函数是如何知道应该访问的是d1对象还是d2对象呢?
C++中设计了⼀个隐含的this指针来解决访问对象的问题。所以类的成员函数中访问成员变量,本质都是通过this指针访问的。
编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this 指针。所以Stack类中函数的真实原型是(注意,这种写法是错误的,编译器会报错):
#include<iostream>
class Stack
{
public:
void Init(Stack* const this, int n = 4)
{
this->a = (int*)malloc(sizeof(int) * 4);
this->capacity = 4;
this->top = 0;
}
void Push(Stack* const this, int x)
{
if (top == capacity)
{
int newcapacity = 2 * capacity;
int* tmp = (int*)realloc(a, sizeof(int) * newcapacity);
a = tmp;
capacity = newcapacity;
}
a[top++] = x;
}
void Destroy(Stack* const this)
{
free(a);
a = nullptr;//空指针
top = capacity = 0;
}
private:
int* a;
int top;
int capacity;
};
int main()
{
//Stack类实例化出对象st1、st2
Stack st1;
Stack st2;
st1.Init(&st1);
st2.Init(&st2);
st1.Destroy(&st1);
st2.Destroy(&st2);
return 0;
}
但C++规定不能在函数参数的位置显示的写this指针,编译器会报错(因为编译时编译器会自己处理),但是可以在函数体内显示使⽤this指针。
正确写法为:
void Init(int n = 4)
{
this->a = (int*)malloc(sizeof(int) * 4);
this->capacity = 4;
this->top = 0;
}
通过调试,我们看到: