这是对这个问题的跟进。考虑以下示例:
#include <iostream>
namespace MyProject {
class string {
public: string() { std::cout << "Callin string constructor" << std::endl; }
};
}
namespace Other {
class string {};
}
namespace MyProject {
using Other::string;
}
namespace MyProject {
void useString() {
const string s;
}
}
int main() {
MyProject::useString();
}
在这里,编译器在该行正确地抛出了一个错误using Other::string
,抱怨该string
命名空间中已经存在一个来自先前class string
定义的声明。
现在考虑一下:
#include <iostream>
namespace MyProject {
class string {
public: string() { std::cout << "Callin string constructor" << std::endl; }
};
}
namespace Other {
class something {};
using string = something;
}
namespace MyProject {
using Other::string;
}
namespace MyProject {
void useString() {
const string s;
}
}
int main() {
MyProject::useString();
}
这里没有编译错误:我成功地string
用一个新的声明隐藏了我之前的声明。
为什么第二种情况没有错误?是不是因为
using string = something
is not an actual declaration,因为它是别名,而真正的声明是针对something
名称的,编译器只能发现实际声明之间的冲突,所以在这种情况下,它会认为我真的在声明something
andstring
,并且是可以吗?这不是很危险吗?我的意思是,如果这些事情在程序员没有意识到的情况下发生在单独的头文件中,他/她最终可能会使用一个可能与他/她认为的完全不同的标识符,并且编译器不会说任何东西......