迷糊了很久,终于算是有点理解了。这里做个记录。
1.什么时候进行类型名字查找
当编译器发现一个新的类型时,比如myint,它只查找myint出现之前的语句,不会查找其之后的语句。这就是“先声明,后使用”。例如下面的代码:
#include <iostream>
using namespace std;
class A{
public:
typedef int myint;
public:
void show(myint x)
{
cout << x << endl;
}
};
int main()
{
A a;
a.show(10);
return 1;
}
编译器解析到show函数的myint标志符时,发现在这个声明以前就有typedef说明了它是一个类型,所以不会出现编译错误。但是如果将这个typedef语句换个位置,即如下所示:
#include <iostream>
using namespace std;
class A{
public:
void show(myint x)
{
cout << x << endl;
}
public:
typedef int myint;
};
int main(){A a;a.show(10);return 1;}
那么就会发生编译错误了。
2.类成员函数的形参和函数体均处于类作用域中这个规定适用于类成员函数在类体外定义的情况。所以下列代码就存在覆盖的问题了。
#include <iostream>
using namespace std;
class A{
public :
A():x(11){}
void show1(int x){cout << x << endl;}
void show2(int x){cout << this->x << endl;}
void show3(int x){cout << A::x << endl;}
private :
int x;
};
int main()
{
A a;
a.show1(10);
a.show2(10);
a.show3(10);
return 1;
}
上述代码,只有采用显式的this或者类作用符就避免了覆盖的问题了。
函数的形参和函数体的数据类型名字的解析是先查找类作用域,然后查找更大范围,但是这个查找依旧是只查询需要解析的类型名字之前的声明,这和第一点是一样的。
3.成员函数的返回类型不一定在类作用域中,除非用类作用域显示给出。
这个“不一定”体现在:如果成员函数是在类体中定义的,那么返回类型旧在类作用域中,如果不是在类体中定义的,那么就不在类作用域中。
如下列代码:
#include <iostream>
using namespace std;
class A{
public:
typedef int myint;
public:
myint show1(myint x);
myint show2(myint x)
{
cout << x << endl;
}
};
myint A::show1(myint x)//myint默认是不在类作用域的
{
cout << x << endl;
}
int main()
{
A a;
a.show1(10);
a.show2(10);
return 1;
}
show1的返回类型myint不在类作用域中,编译器解析的时候在类外找,所以就会发生编译错误了。
4.关于typedef int myint 语句的位置
查看STL的源码,发现它们的typedef语句的位置都是在类的前面段,这样设计肯定是有原因的。原因在1点中就已经阐述了:避免编译解析发生错误。这是它的所在位置,那么这句话的访问控制符应该怎么设计呢?观察stl的例子,发现,它们将typedef语句设定为public,也是,只有这样我们才能使用vector<int>::iterator此类的语句了。这也透露出,typedef也是受访问控制符的限定的,我们应该根据自己的需求设定typedef语句的访问控制符。