一.类的数据成员绑定时机
a.研究成员函数的返回值
string myvar;//全局变量,字符串型
class A
{
public:
int myfunc()
{
cout << ::myvar.c_str() << endl;//全局变量;
cout << myvar << endl;// 成员函数;
return myvar;//int类型的;
}
int myfunc2();
private:
int myvar; //同全局变量名相同,但类型不同;
};
int A::myfunc2()
{
return myvar;// int类型
}
string func()
{
cout << myvar << endl;//string类型的;
return myvar;//string类型;
}
编译器对成员函数myfunc的解析,是在整个类A定义完毕之后才开始的。当在内类找不到才会去类外找;所以无论是myfunc()还是myfunc2()这个成员函数的返回类型都是我们在类内定义的int型的myvar;类外的普通全局函数的返回类型也自然是在类外定义的string类型的myvar。
b.研究成员函数的参数问题
typedef string mytype;// 定义mytype为string类型
class B
{
public:
void myfunc(mytype temp)//string
{
//m_value = temp;// int=string 肯定报错;
}
void myfunc1(mytype t);// string
private:
mytype a;// string
typedef int mytype; //定义mytype为int类型;
mytype m_value; // int
};
void B::myfunc1(mytype t)//在类外写成员函数的时候 mytype被认为是int类型;这里会报错,
{
m_value = t;
}
void myfunc(mytype tmpvalue)
{
string m_value = tmpvalue;
}
对于成员函数的参数,是在编译器最近一次确定mytype类型的时候被决定的,
如果类内有typedef这种定义的话,放在类的最开头位置,让类成员可以尽早的看见;
二.进程内存空间布局(不同的数据在内存中会有不同的保存位置)
class A
{
public:
int m_i;
static int m_si;// 声明,编译器并不会分配空间;
int m_j;
static int m_sj;
int m_k;
static int m_sk;
};
int A::m_si = 0;
int A::m_sj = 0;
int A::m_sk = 0;
int main()
{
A a; // 栈。
cout << sizeof(a) << endl;
printf("m_i的地址=%p\n", &a.m_i);//003C FA58 栈。
printf("m_j的地址=%p\n", &a.m_j);//003C FA5C
printf("m_k的地址=%p\n", &a.m_k);//003C FA60
// 普通成员变量的储存顺序,是按照在类中定义顺序从上到下来的;
// 比较晚出现的变量在内存中有更高的地址;
printf("m_si的地址=%p\n", &a.m_si);//00C0 A3D0 在编译的时候就确定下来了;
printf("m_sj的地址=%p\n", &a.m_sj);//00C0 A3D4 数据段
printf("m_sk的地址=%p\n", &a.m_sk);//00C0 A3D8
A* p = new A();
printf("p的地址=%p\n", &p);//003 CFA4C 栈。
printf("m_i的地址=%p\n", &p->m_i);//0087 FC40 堆。
printf("m_j的地址=%p\n", &p->m_j);//0087 FC44
printf("m_k的地址=%p\n", &p->m_k);//0087 FC48
printf("m_si的地址=%p\n", &p->m_si);//00C0 A3D0 数据段
printf("m_sj的地址=%p\n", &p->m_sj);//00C0 A3D4
printf("m_sk的地址=%p\n", &p->m_sk);//00C0 A3D8
return 0;
}
三.边界调整(内存对齐)
class A
{
public:
int m_i;
int m_j;
int m_k;
char c;
};
int main()
{
cout<<sizeof(A) << endl;//,内存四字节对齐,结果为16
return 0;
}
#pragma pack(1) // 设置为1字节对齐;
class A
{
public:
int m_i;
int m_j;
int m_k;
char c;
};
#pragma pack() //回复原来的字节对齐;
int main()
{
cout<<sizeof(A) << endl; // 内存不对齐,结果为13;
return 0;
}
四.成员偏移量值的打印
#define GET(A,m) (int)(&((A*)0)->m)
class A
{
public:
int m_i;
int m_j;
int m_k;
char c;
void printf1()// 方法1;
{
cout << "打印成员变量偏移量-------" << endl;
printf("m_i=%p\n", &A::m_i);
printf("m_j=%p\n", &A::m_j);
printf("m_k=%p\n", &A::m_k);
printf("c=%p\n", &A::c);
}
void printf2()// 方法2;
{
cout << "打印成员变量偏移量-------" << endl;
cout << GET(A, m_i) << endl;
cout << GET(A, m_j) << endl;
cout << GET(A, m_k) << endl;
cout << GET(A, c) << endl;
}
virtual void func() {}// 在所有成员变量的最前面增加了一个虚函数表指针;
};
int main()
{
A a;
a.printf1();
a.printf2();
// 方法3:
// 成员变量指针:
int A::* p = &A::m_i;
printf("m_i的偏移量=%d\n", p);
return 0;
}
我的内容可能写的比较潦草,如果需要笔记内容相对应的课程,请关注并私信我。