关于 第三章data member的绑定 的读书笔记

来源:互联网 发布:减肥不反弹知乎 编辑:程序博客网 时间:2024/06/08 04:21

书里以一个小程序开始,如下:

extern int x; //对外部定义的一个变量的引用

class test

{

public:

test(float, float, float);

//这里被传回和绑定的是按个x?

float test() const { return x; }

void test(float new_x) { new_x = x; }

private:

float x, y, z;

};

       这个地方我刚看到时,首先想到的类中定义的float x,是基于局部变量屏蔽全局变量的原则,但仔细一想,又有些不对,因为类中对x的定义出现在函数后方,上面的局部变量屏蔽全局变量的原则是行不通的。然后又写程序测试了一遍,结果确实是类中的定义x,即外部的int x是被屏蔽了。

       带个疑惑接着往下看时,书中说到了早期c++的两种防御编程风格。

一种是把数据成员的声明放在class的开头处,以确保正确的绑定,这里我觉得应该是类似于局部变量屏蔽全局变量的原则吧。

另一种是将成员函数(好像c++默认成员函数是inline的)的定义放到class的外头,类里只有其的声明,这也可以保证正确的绑定,因为这种方法中我看到函数的定义时,已经知道类中的数据成员。

      接着根据这些提出了两个rules,大意应该是对成员函数的评估求值在整个类声明完成之后进行。这就很好解释了最开始的问题,对成员函数的data member的绑定发生类声明完成之后。

然而,书里接着说到一个问题还是让我有些惊讶。该规则对member function的参数列表并不起作用。参数列表中的名称还是会在第一次遭遇时会被适当的决议。因此extern和nested typed names之间的非直觉绑定还是会放生。见书中的这个例子:

typedef int length;
class test
{
public:

//这里函数me的参数列表val的类型是int,而不是float
void me(length val) { cout << sizeof(val) << endl; _val = val; }
length me() { return _val; }

private:
typedef float length;
length _val;
};

在vs2010下编译时,会有这样的警告:


1>d:\projects\test_for_inside_c++object\test_for_inside_c++object\1.cpp(35):warning C4244: “=”: 从“length”转换到“test::length”,可能丢失数据
1>d:\projects\test_for_inside_c++object\test_for_inside_c++object\1.cpp(36): warning C4244: “return”: 从“test::length”转换到“length”,可能丢失数据


       这应该是说明了对参数列表中的类型判断是即时的,如果将typedef int length;注释掉则会显示语法错误。

       如果将数据成员的声明放到类声明的开头,则上面的警告不会出现。

       这里我又想到了一个问题,如果将member function的定义放到类外面,即类里只有其声明。会不会出现和类似将数据成员放到类开头这样的结果呢?代码如下:

typedef int length;
class test
{
public:
inline void me(length val); 
inline length me() ;
private:
typedef float length;
length _val;
};
void test::me(length val) { cout << sizeof(val) << endl; _val = val; }
length test::me() { return _val; }

编译得到的结果另我很吃惊:


1>d:\projects\test_for_inside_c++object\test_for_inside_c++object\1.cpp(42): error C2511: “void test::me(test::length)”:“test”中没有找到重载的成员函数
1>d:\projects\test_for_inside_c++object\test_for_inside_c++object\1.cpp(33) : 参见“test”的声明
1>d:\projects\test_for_inside_c++object\test_for_inside_c++object\1.cpp(43): warning C4244: “return”: 从“test::length”转换到“length”,可能丢失数据


从编译的结果可以得出这样的结论,将member function的定义放到类外面,对结果不会有什么影响。即对参数列表中的判断是即时的,不会等到后期判断。我觉得可以从两个地方得出伤处结论:一是见这个warningwarning C4244: “return”: 从“test::length”转换到“length”,可能丢失数据,二是那个error,此例中将类外面定义的val当成float类型,类外面定义的me(length val)和类里定义的me(length val)将不是同一个函数了,他们的参数列表中参数的类型发生的变化,因此会匹配失败。


       写到这里,真是感触良多,以前看到一些说法说是尽量将member function的定义放到类的外部,以及将数据成员的定义放到类的最后面,这好像是从类封装的角度说的,不过从这里看,好像也是有些关联。

原创粉丝点击