深入理解C++中 class的成员变量,和成员函数
下文的第一段代码块中给出了一个普通的类Dog的实现,有私有成员dId,有bark()成员函数描述dog的行为。bark中有使用到成员dId。
在main函数中打印了Dog的大小4byte,可以想见它只存储了成员dId,成员函数并没有包括在类Dog中。然后是bark的普通通访问方式,创建对象,通过.访问。
之后创建了一个函数指针barkptr,它无返回值,有一个形参Dog*,可以看出barkptr和Dog::bark唯一的区别就是多了个形参Dog*,巧合的是正好bark可以赋值给barkptr,并且我们通过给barkptr传递一个Dog对象tyke的指针还能访问到bark函数,且bark函数还能访问到tyke的私有成员dId。
#include <iostream>
//Dog是个普通的类
class Dog{
private:
int dId;
public:
Dog(int id) : dId(id){}
void bark(){
std::cout << "I am NO." << dId << ",\tbark! bark!" << std::endl;
}
};
int main(){
std::cout << "sizeof Dog: " << sizeof(Dog) << std::endl;
//普通访问
Dog spike(100);
spike.bark();
//获取Dog中成员函数bark的函数指针
void(*barkptr)(Dog*) = ( void(*)(Dog *) )&Dog::bark;
//通过this指针访问
Dog tyke(101);
barkptr(&tyke);
}
//执行结果
sizeof Dog: 4
I am NO.100, bark! bark!
I am NO.101, bark! bark!
正是因为,C++中对类成员的存储其实类似于C中的结构体,将一组数据成员按序排在一起(这个过程中考虑字节对齐)。而至于对成员函数的存储就类似于C中的普通函数,只是隐式的在成员函数中添加了一个结构体指针,指向数据成员。正数因为这样,上边的访问方式才得以实现。可以看出,C++中的类,其实只是在C的结构体和函数的基础上的少许变更,在加上C++新发明的作用域的概念而实现的。
下文是利用C语言的结构体、全局函数和namespace对C++中类的示意说明。当然从结构体到类远没有这么简单,但我们至少能理清C++类中的成员和成员函数,和C中的什么是相似相对应的。
#include<stdio.h>
namespace Dogc
{
typedef struct
{
int dId;
}Dogc;
void bark(Dogc *this_ptr)
{
printf("I am NO.%d,\tbark! bark!\n", this_ptr->dId);
}
}
int main(){
std::cout << "sizeof Dogc: " << sizeof(Dogc) << std::endl;
Dogc tykec;
tykec.dId = 12580;
bark(&tykec);
return 0;
}
#C++#
