在学习C++一开始,我们就知道在使用类型、变量和函数时需要先定义。名字查找的过程比较直截了当:
- 首先,在名字所在的块中寻找其声明语句,而且只找名字使用之前出现的声明
- 如果没有找到,继续查找外层作用域,一样也必须在名字所在块之前出现的声明才被考虑
- 如果最终没有找到匹配的声明,则程序报错
当然,对于定义在类内的成员函数中的名字与上述的查找规则有所区别,类的定义分两步处理:
- 首先,编译成员的声明
- 直到类全部可见后,才编译函数体。
成员函数中使用的名字按照如下方式解析:
- 首先,在成员函数内查找该名字的声明,只有在名字使用前出现的声明才被考虑
- 若成员函数内没找到该声明,则在类内继续查找;类内的所有成员都可以被考虑,不区分出现的前后顺序
- 类内也没有,则按一般查找顺序,在外层作用域继续查找
例如下面代码:
#include <iostream>
using namespace std;
typedef double Money;
Money price = 10;
class Account
{
public:
Money getPrice() const
{
return price;
}
private:
Money price = 20;
typedef int Money;
};
int main()
{
Account acc;
cout << typeid(decltype(acc.getPrice())).name() << endl;
cout << acc.getPrice() << endl;
}
输出结果为:
double
20
对于Account::price类型Money和Account::getPrice()返回值类型Money,在他们之前出现且离他们最近的是typedef double Money,所以类型是double。
而Account成员函数getPrice()中的price,最近的是类内的price。
再看一个代码:
#include <stdio.h>
class abc;
void del(abc *pobj)
{
delete pobj;
}
// 下面的代码将会报错
/*
void del(abc *pobj)
{
abc->show();
delete pobj;
}
*/
class abc
{
public:
abc()
{
printf("abc\r\n");
}
~abc()
{
printf("~abc\r\n");
}
void show()
{
printf("this is abc\r\n");
}
};
int main()
{
abc *pobj = new abc;
del(pobj);
}
输出:
abc
因为del中的参数abc是之前声明的abc,没有析构函数。