每一个class object必须有足够的大小以容纳它所有的nonstatic data members。有时候其值较大,原因是:
- 1、由编译器自动加上额外data members,用以支持某些语言特性(主要是各种virtual特性)
- 2、因为alignment(边界调整)的需要。(如:一些机器要求结果为4bytes的倍数)。
3.1 Data member的绑定(类内成员与全局数据的冲突性问题)
一、举例
extern float x;
class Poind3d{
public:
float X() const{return x;}
private:
float x,y,z;
}
Poind3d类中的函数X()会返回类内部private中的x,而不是返回全局的extern float x.
但是,早期c++标准并非如此:
二、早期c++标准的数据成员绑定
- 为了防止类内数据成员与全局数据成员产生冲突,早期C++设置了下面两种防御性程序设计风格
- 风格1:所有的数据成员放在class声明处
#include "foo.h"
class Point3d
{
float x, y, z;
public:
//...
float X()const { return x; }
//...
};
- 风格2:所有的内联函数,不管大小都放在类声明之外
#include "foo.h"
class Point3d
{
float x, y, z;
public:
//...
float X()const;
//...
};
inline float Point3d::X()const
{
return x;
}
三、现代c++标准的数据成员绑定规则
- 对数据成员的分析,只有在整个class的声明都出现了才开始(直到出现classs右大花括号“}”)
extern int x;
class Point3d
{
public:
//...
//该函数本身的分析不会立即执行,而是等到class声明的右大括号“}”出现才开始
float X()const { return x; }
//...
private:
float x, y, z;
};
//在此,class的分析才开始,所以X()成员函数分析的是自身类的x数据成员,而不是全局的x
四、参数列表分析
参数列表的规则与上述数据成员分析规则不同
-
- 尽管内部类型在private中也使用了typedef进行了声明,但是public中的两个mumble成员函数使用的都是全局的typedef声明
typedef int length;//全局
class Point3d
{
public:
void mumble(length val) { _val = val; } //使用的是全局声明
length mumble() { return _val; } //使用的是全局声明
private:
typedef float length; //局部
length _val;
};
如果把全局声明注释掉,会出现如下情况:
- 为了正确使用类内的typedef声明,应将类内typedef放于class声明最前面
typedef int length; //全局
class Point3d
{
private:
typedef float length; //局部
length _val;
public:
void mumble(length val) { _val = val; } //使用的是局部声明
length mumble() { return _val; //使用的是局部声明
};