this指针[ZT]
先说明何谓this指针:
class CA
{
long a;
void A(long e);
void B(long e);
};
上面的类定义实际上如下:
struct s_CA
{
long a;
};
void CA_A(s_CA *this, long e);
void CA_B(s_CA *this, long e);
因此:
CA a; // 此时实际为:s_CA a; CA_CA(&a); // 调用构造函数
a.A(34); // 此时实际如下:CA_A(&a, 34);
因此所谓的this指针就是struct s_CA的一个指针,而所谓的类实例其实就是一个结构的实例。而当出现虚函数时,假设如下:
接口IA为: 接口IB为:
struct IA struct IB
{ {
void A(long e) = 0; void B(long e) = 0;
}; };
而CA派生自IA和IB,即实现IA和IB(用ATL的方式),此时s_CA变成如下:
struct s_CA
{
void *pvt_A; // 由于IA所引入的虚函数地址指针,也就是所谓的一份函数拷贝
void *pvt_B; // 由于IB所引入的虚函数地址指针,也就是所谓的一份函数拷贝
long a;
};
此时:
CA a;
IA *pA = static_cast<IA*>(&a); // 此时pA == &a
IB *pB = static_cast<IB*>(&a); // 此时pB == &a + 4,跳过pvt_A,由static_cast这个指令进行转换的
pA->A(34); // 此时实际为(*pA->pvt_A[0])(pA, 34);
pB->B(34); // 此时实际为(*pB->pvt_B[0])(pB, 34);
而pA->pvt_A[0]的函数原型为void CA_A(IA *this, long e);
而pB->pvt_B[0]的函数原形为void CA_B(IB *this, long e);
因此就有函数CA_A和CA_B,而CA_A的this指针是IA*,CA_B的this指针是IB*,即调用接口函数时传递的this指针就是那个接口的指针,但是数据是怎么传递的呢?即编译器如何知道IA*加上8个字节后就是成员变量a的值?
很简单,因为CA_A和CA_B是类CA实现的,因此编译器在编译CA_A时知道此时传进来的this+8就是成员变量a的地址,在CA_B时知道此时传进来的this+4就是成员变量a的地址,因为编译器在编译这两个函数时是知道类CA的定义的,即编译器知道如下:
class CA : public IA, public IB
{
long a;
void A(long e);
void B(long e);
};
所以编译器知道传进来的this到底是个什么类的实例,因而可以表现出通过传递虚函数列表的指针就达到了传递数据成员的现象。
class CA
{
long a;
void A(long e);
void B(long e);
};
上面的类定义实际上如下:
struct s_CA
{
long a;
};
void CA_A(s_CA *this, long e);
void CA_B(s_CA *this, long e);
因此:
CA a; // 此时实际为:s_CA a; CA_CA(&a); // 调用构造函数
a.A(34); // 此时实际如下:CA_A(&a, 34);
因此所谓的this指针就是struct s_CA的一个指针,而所谓的类实例其实就是一个结构的实例。而当出现虚函数时,假设如下:
接口IA为: 接口IB为:
struct IA struct IB
{ {
void A(long e) = 0; void B(long e) = 0;
}; };
而CA派生自IA和IB,即实现IA和IB(用ATL的方式),此时s_CA变成如下:
struct s_CA
{
void *pvt_A; // 由于IA所引入的虚函数地址指针,也就是所谓的一份函数拷贝
void *pvt_B; // 由于IB所引入的虚函数地址指针,也就是所谓的一份函数拷贝
long a;
};
此时:
CA a;
IA *pA = static_cast<IA*>(&a); // 此时pA == &a
IB *pB = static_cast<IB*>(&a); // 此时pB == &a + 4,跳过pvt_A,由static_cast这个指令进行转换的
pA->A(34); // 此时实际为(*pA->pvt_A[0])(pA, 34);
pB->B(34); // 此时实际为(*pB->pvt_B[0])(pB, 34);
而pA->pvt_A[0]的函数原型为void CA_A(IA *this, long e);
而pB->pvt_B[0]的函数原形为void CA_B(IB *this, long e);
因此就有函数CA_A和CA_B,而CA_A的this指针是IA*,CA_B的this指针是IB*,即调用接口函数时传递的this指针就是那个接口的指针,但是数据是怎么传递的呢?即编译器如何知道IA*加上8个字节后就是成员变量a的值?
很简单,因为CA_A和CA_B是类CA实现的,因此编译器在编译CA_A时知道此时传进来的this+8就是成员变量a的地址,在CA_B时知道此时传进来的this+4就是成员变量a的地址,因为编译器在编译这两个函数时是知道类CA的定义的,即编译器知道如下:
class CA : public IA, public IB
{
long a;
void A(long e);
void B(long e);
};
所以编译器知道传进来的this到底是个什么类的实例,因而可以表现出通过传递虚函数列表的指针就达到了传递数据成员的现象。