深入探索c++对象模型(九、成员变量的绑定)
创始人
2024-05-26 22:29:00
0

这一篇我们开启《深入探索c++对象模型》的第3章 Data语义学,第3章开头介绍了对象的大小,这个我们在第一篇的时候已经讲过了,不过第一篇介绍的比较少,只是简单的描述了几种情况下类对象的大小,忘记的可以回去看下第一篇,我也忘记了,刚刚也回去看了下,哈哈哈。

9.1 成员变量绑定时机

我们现在写类变量,经常是在后面写类变量,类方法经常写前面比如:

// 类中再定义一个x
class A
{
public:float X() const {return x;}   // 访问的是类中的xfloat GX() const {return ::x;}	// 这个访问的是全局的xprivate:float x;
};

这种写法是不是习以为常,下面我们就来谈论谈论一个细思极恐的东西。

9.1.1 类中定义函数访问类变量

我们来看看例子:

#include using namespace std; //定义一个全局的变量x
float x = 11;// 可以提到这里试试// 类中再定义一个x
class A
{
public:float X() const {return x;}   // 访问的是类中的xfloat GX() const {return ::x;}	// 这个访问的是全局的xprivate:float x;
};int main(int argc, char **argv)
{A a;cout << "x = " << a.X() << " GX = " << a.GX() << endl;return 0;
}

这个例子专门在全局部分添加了一个float x = 11;以这个来测试一下编译器到底是找那个x。

我们编译,执行一下看看:

[mmog@localhost 09]$ ./9_1
x = -8.02677e-35 GX = 11

A::X() 访问的哪个x,应该都知道吧,就是访问类中的x,编译器对成员函数的解析,是整个类A定义完成之后,才进行的

A::GX()访问的就是全局的x,要想访问全局的x,需要使用::

9.1.2 类外定义函数访问类变量

我们在尝试一下,把函数体放在类外面试试:

float x = 11;
// 类中再定义一个x
class A
{
public:float X() const;float GX() const;private:float x;
};float A::X() const {return x;}		// 访问的是类中的xfloat A::GX() const {return ::x;}	// 这个访问的是全局的x

这样结果也是一样的。

刚刚想到一种是把函数移动到类的前面,这样就编译报错,因为类A还没加载,找不到类A。

9.1.3 内联函数访问类变量

还有一个内联函数:

float x = 11;class A
{
public:float X() const;float GX() const;inline float XX() const {return x;}private:float x;
};

内联函数也是在类A定义完之后,才进行解析的。

float x = 11;class A
{
public:float X() const;float GX() const;float XX() const;private:float x;
};float A::X() const {return x;}float A::GX() const {return ::x;}inline float A::XX() const {return x;}

在外面定义也是如此。

侯捷老师说的以前的c++编译器的事,这里就不提,都是旧时代的东西了,我们现在是新时代了,哈哈哈。

9.2 使用typedef定义变量绑定时机

既然上面是c++后来的标准改变了,那我们就试试使用typedef的方式定义下变量。

9.2.1 类中定义函数访问

我们先来看看类中定义函数的情况:

int _val = 0;
//定义一个全局的变量x
typedef int length;// 类中再定义一个x
class A
{
public:void mumble(length val) {_val = val;}   // 编译出错,_val是float类型,val是int类型,两个类型不相等length mumble() {return val;}           // 这个返回的是int 类型private:typedef float length;length _val;                        // 这个是float 类型};

这样编译会出错,根据就近原则,类的函数应该是样的:

void mumble(int val) {_val = val;}   // _val是float 所以出错 
int mumble() {return val;} 

9.2.2 类外定义函数访问

类中定义有问题,那我们看看类外的,虽然我们直接告诉我们这个也会出错,但还是要分析分析。

int _val = 0;
//定义一个全局的变量x
typedef int length;// 类中再定义一个x
class A
{
public:void mumble(length val);                // 这个是int类型length mumble() {return val;}           // 这个返回的是int 类型private:typedef float length;length _val;                        // 这个是float 类型};void A::mumble(length val)      // 这个也报错,没有定义这个类型,这个length是float类型
{_val = val;
}void mumble(length val)      // 普通函数是正确的,这是找全局的length,是int类型
{int _val = val;
}

很明显这种写法也出错了,不过报错的是另一个问题,我们来分析一下,

根据就近原则和类作用域:

// 类中函数,提取出来分析 
void mumble(int val);                // 这个是int类型//类外内存,因为类已经定义了,所以这个是floatvoid A::mumble(float val)      // 这个也报错,没有定义这个类型,这个length是float类型
{_val = val;
}

所以这个报错是类中没有定义这个函数。

9.3.3 正确玩法

经过上面的分析,对于成员函数参数:是在编译器第一次遇到length的时候被决定,所以length第一次被遇到编译器只看到了typedef int length; 所以函数都被翻译成int。

为了类中尽早看到类类型length,所以typedef定义要被提前,这样就不会出现奇奇怪怪的问题了。

int _val = 0;
//定义一个全局的变量x
typedef int length;// 类中再定义一个x
class A
{typedef float length;			// 提前
public:void mumble(length val);                // 这个是float类型length mumble() {return _val;}           // 这个返回的是float 类型private:length _val;                        // 这个是float 类型};void A::mumble(length val)
{_val = val;
}void mumble(length val)      // 普通函数是正确的,这是找全局的length,是int类型
{int _val = val;
}

提前能解决很多问题,下次注意,如果用typedef的话,记得提前。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...