类作用域中名字查找的思考(《C++ primer》第四版P382)

1、问题的引入

1).观察以下第一块代码:

#include <iostream>using namespace std;class Screen{public:void test(){dummy_fcn( );}void dummy_fcn( ){}};此代码编译无错误。。。。。。。。。。。。。。。

2).再看以下第二块代码:

#include <iostream>using namespace std;void test(){dummy_fcn( );}void dummy_fcn( ){}此代码编译出错。。。。。。。。。。。。。

3).再看第三块代码:

#include <iostream>using namespace std;void dummy_fcn( ){}void test(){dummy_fcn( );}此代码编译也无错误。。。。。

4).第四块代码:

#include <iostream>using namespace std;class Screen{public:typedef std::string::size_type index;void test(){dummy_fcn( );}void dummy_fcn( ){cursor = width * height;}private:index cursor;index height, width;};此代码编译并无错误。。。。。。。。。。。。。。。。。。。。。。

5).第五块代码:

#include <iostream>using namespace std;class Screen{public:void test(){dummy_fcn( );}void dummy_fcn( ){cursor = width * height;}private:index cursor;index height, width;typedef std::string::size_type index;};此代码编译出错。。。。。。。。。。。

2、发现

发现1:对比第1、2、3块代码,我们发现在类中,名字查找是比较特殊的。对于普通的函数名字,编译器只会从其之前的地方查找是否声明,若无声明就报错(如代码2)。。而对于类中的名字来说,编译器将会在整个类作用域中进行查找(如代码1),若找不到,会进一步在整个类的定义之前进行查找。

发现2:对比第4、5块代码,,其不同之处仅仅在于index类型变量的定义位置。可知,编译器在对类的定义进行编译时,并不会在整个类作用域内查找类型的定义(此例中index的定义)。

3、思考

以上的两点发现其实和类定义的“两步编译”有关。。见《C++ primer》第4版中P382,

“类定义实际上是在两个阶段中处理的:

(1)首先,编译成员声明;

(2)只有在所有成员出现之后,才编译它们的定义本身。

其中发现2对应“两步编译”中的第一步(《C++ primer》中称为类成员声明的名字查找),而发现1对应第二步(《C++ primer》中称为类成员定义中的名字查找)。

3.1第一步编译的思考

在第一步编译所有成员声明中,不会检查成员函数定义中的函数调用(如发现2中的例子)。此时只会对成员声明中的类名是否定义进行检查(如上例中的index),这种检查会分为两步:

1)在类中该类名使用之前进行查找

2)在整个类定义之前进行查找

3.2第二步编译的思考

在第二步编译它们的定义时,会进一步检查成员函数中的函数调用(如发现1中的例子)。此时的检查会分为三步:

1)在成员函数局部作用域中进行查找

2)在整个类定义域中进行查找。之所以能够在整个类定义域中进行查找,是因为经过了第一步的对所有类成员声明的定义。这也是和普通名字查找不同的地方(如发现1中的例子)

3)在这个类成员函数定义之前(这里不仅仅指类定义之前,因为类成员函数可能是在类外部)进行查找

而不去欣赏今天就开在我们窗口的玫瑰。

类作用域中名字查找的思考(《C++ primer》第四版P382)

相关文章:

你感兴趣的文章:

标签云: