类
C语言中,我们可以使用结构体对数据进行打包封装。
比如:
头文件中
struct tagNode
{
int nRow;
int nCol;
};
void Position(tagNode* pNode, int nRow, int nCol);
cpp文件中
void Position(tagNode* pNode, int nRow, int nCol)
{
pNode->nRow = nRow;
pNode->nCol = nCol;
}
这样做的好处是,我们可以通过头文件就可以知道有哪些数据,以及操作数据的接口(函数)是什么。
但是它的不足之处是:
- C语言中的结构体,大部分时候是用来封装数据,不包含动作。(通过函数指针可以实现封装数据和动作)
- 生活中对事物的看法,往往是“数据”和“动作”一体的。
比如,“人”,有高矮胖瘦、能跑跳等。
而面向对象中的“封装”,指的是,将数据和处理数据的动作封装在一起。
C++中,为了更好的表达封装,在C语言的基础上,改进了struct,提出了class。
C++中的结构体
为了更好的表达面向对象的思想,C++中的结构体,在C的基础上做了改进。
- C++的结构体中,可以定义函数(一般称为“方法”)
- 方法可以直接使用结构体中的数据成员,而不需要通过参数列表传递。
定义方法
struct tagNode
{
int nRow;
int nCol;
void SetPos(int argRow, int argCol)
{
nRow = argRow;
nCol = argCol;
}
void ShowPos()
{
printf("%d,%d\r\n", nRow, nCol);
}
};
方法的调用方式
- 先声明一个C++结构体的变量(一般称为“对象”)
- 可以像调用成员那样,利用“.”的调用方法。
实例如下:
#include <iostream>
struct tagNode
{
int nRow;
int nCol;
void SetPos(int argRow, int argCol)
{
nRow = argRow;
nCol = argCol;
}
void ShowPos()
{
printf("%d,%d\r\n", nRow, nCol);
}
};
int main(int argc, char* argv[])
{
tagNode node1;
node1.SetPos(10, 10);
node1.ShowPos();
node1.SetPos(20, 20);
node1.ShowPos();
return 0;
}
方法的原理
不同对象的同名方法,在汇编级别,是一样的。
int main(int argc, char* argv[])
{
tagNode node1;
tagNode node2;
node1.SetPos(1, 1);
node1.ShowPos();
node2.SetPos(2, 2);
node2.ShowPos();
return 0;
}
通过以上代码发现,node1.SetPos和node2.SetPos是同一个方法(SetPos)。
既然是调用同一个方法,那么为什么设置结构体变量分别设置了node1和node2,并且node2不会覆盖node1呢?
要解答这个问题,就需要揭开这背后的秘密:C++中的this指针。
this是C语言中的关键字,代表指向当前对象的指针,实际上,刚刚所说的方法可以直接调用结构体中的成员,其实是因为C++编译器为每个成员自动加上了this->
void SetPos(int argRow, int argCol)
{
nRow = argRow;
nCol = argCol;
}
以上代码的实际样子其实是:
void SetPos(int argRow, int argCol)
{
this->nRow = argRow;
this->nCol = argCol;
}
this指针是如何传递的?
对于对象的方法调用,使用的调用约定不是C语言中的约定、stdcall等,而是使用了this调用约定。
C++中结构体方法的约定是thiscall
什么是thiscall?以微软编译器为例:
它会从右往左传参,this指针中保存的地址存放在ecx中,对象地址会通过**ecx(寄存器)**传递。
关于对象的方法调用的特殊之处
- 采用thiscall约定
- thiscall会自动传递一个this指针,this指针指向当前调用的对象的首地址。
- 微软cl编译器,通过ecx寄存器传递this指针。
引出主角:类
C++中对C语言中struct的改进,使我们可以更好的面向对象,可以更方便的将数据和动作封装到一起,借助thiscall约定和this指针,也更不容易混淆需要操作的参数。
为了更加凸显C++中封装同C语言中的封装的区别,C++发明了关键字class。
C++中的class和C++中的struct几乎是一样的,唯一的区别是默认访问权限不一样。
- 问题1:C语言和C++中的struct有什么不同?(封装)
- 问题2:C++中的struct和class有什么不同?
默认访问权限
在C++中有三种权限
- public:方法和成员可以被所有人使用
- private:方法和成员只可以被当前类中的方法使用
- protectd
当是struct时:
#include"stdafx.h"
#include <iostream>
struct tagNode
{
int nRow;
int nCol;
void SetPos(int argRow, int argCol)
{
this->nRow = argRow;
this->nCol = argCol;
}
void ShowPos()
{
printf("%d,%d\r\n", nRow, nCol);
}
};
int main(int argc, char* argv[])
{
tagNode node1;
tagNode node2;
node1.SetPos(1, 1);
node1.ShowPos();
node2.SetPos(2, 2);
node2.ShowPos();
return 0;
}
像以上这样做可以的,但是当struct换成class后:
#include"stdafx.h"
#include <iostream>
class tagNode
{
int nRow;
int nCol;
void SetPos(int argRow, int argCol)
{
this->nRow = argRow;
this->nCol = argCol;
}
void ShowPos()
{
printf("%d,%d\r\n", nRow, nCol);
}
};
int main(int argc, char* argv[])
{
tagNode node1;
tagNode node2;
node1.SetPos(1, 1);
node1.ShowPos();
node2.SetPos(2, 2);
node2.ShowPos();
return 0;
}
就会报以上错误。
更改:当在class下添加public后,就可以了。
结论:
- class的默认访问权限是private
- struct默认访问权限是public
权限管理的好处
权限管理可以使我们将一些不能修改的数据用private给予限制,防止被修改,保证了数据的安全。