学习数据结构,用到了输入输出运算符重载,结果编译之下,错误重重,,随即停止学习进度,追查祸源,在花费巨大脑力与时间成本之后,终于知自己错误之所在,定位于名字空间之困扰。为牢记教训,写一简化版本记录 debug 过程如下,警示自己。
问题:
有如下两个代码文件:
// 20060816_operator.cxx
2 using namespace std;
3 #include " 20060816_operator.h "
4 int main( int argc, char * argv[])
5 {
6 const std:: string GHH( " GuoHonghua " );
7 Honghua ghh(GHH);
8 cout << ghh << endl;
9 return 0 ;
10 }
// 20060816_operator.h
2 #define _20060816_OPERATOR_GHH_ 1
3
4 // Author : GuoHonghua
5 // Date : 2006.08.16
6 // File : 20060816_operator.h
7
8 #include < iostream >
9 #include < string >
10 class Honghua
11 {
12 friend std::ostream & operator << (std::ostream & os, const Honghua & ghh);
13 public :
14 Honghua( const std:: string & ghh) : _ghh(ghh)
15 {
16 }
17
18 private :
19 std:: string _ghh;
20 };
21
22 std::ostream & operator << (std::ostream & os, const Honghua & ghh)
23 {
24 os << ghh._ghh;
25 return os;
26 }
27
28 #endif // end of _20060816_OPERATOR_GHH_
用上面两个文件建立工程,vc6.0下编译会出错。报告如下:
--------------------Configuration: 20060816_operator - Win32 Debug--------------------
Compiling...
20060816_operator.cxx
f:\ghh_project\cxxdetail\20060816_operator.h(24) : error C2248: '_ghh' : cannot access private member declared in class 'Honghua'
f:\ghh_project\cxxdetail\20060816_operator.h(19) : see declaration of '_ghh'
F:\ghh_project\CxxDetail\20060816_operator.cxx(8) : error C2593: 'operator <<' is ambiguous
Error executing cl.exe.
20060816_operator.exe - 2 error(s), 0 warning(s)
解决:
1. 调整名字空间声明和自定义头文件的次序,如下:
2 #include " 20060816_operator.h "
3 using namespace std;
4 int main( int argc, char * argv[])
5
2. 把类定义于标准名字之内,20060816_operator.h文件修改如下(不推荐)
2 #define _20060816_OPERATOR_GHH_ 1
3
4 // Author : GuoHonghua
5 // Date : 2006.08.16
6 // File : 20060816_operator.h
7
8 #include < iostream >
9 #include < string >
10 namespace std
11 {
12 class Honghua
13 {
14 friend std::ostream & operator << (std::ostream & os, const Honghua & ghh);
15 public :
16 Honghua( const std:: string & ghh) : _ghh(ghh)
17 {
18 }
19
20 private :
21 std:: string _ghh;
22 };
23
24
25 std::ostream & operator << (std::ostream & os, const Honghua & ghh)
26 {
27 os << ghh._ghh;
28 return os;
29 }
30 }
31 #endif // end of _20060816_OPERATOR_GHH_
3. 使用头文件iostream.h代替iostream,比较落后的方式(不推荐!)
2 // #include <iostream>
3 #include < iostream.h >
4 #include < iostream.h >
5 #include " 20060816_operator.h "
6 int main( int argc, char * argv[])
7 {
8 const std:: string GHH( " GuoHonghua " );
9 Honghua ghh(GHH);
10 cout << ghh << endl;
11 return 0 ;
12 }
2 #ifndef _20060816_OPERATOR_GHH_
3 #define _20060816_OPERATOR_GHH_ 1
4
5 // Author : GuoHonghua
6 // Date : 2006.08.16
7 // File : 20060816_operator.h
8 // #include <iostream>
9 #include < iostream.h >
10 #include < string >
11
12 class Honghua
13 {
14 friend ostream & operator << (ostream & os, const Honghua & ghh);
15 public :
16 Honghua( const std:: string & ghh) : _ghh(ghh)
17 {
18 }
19
20 private :
21 std:: string _ghh;
22 };
23
24
25 ostream & operator << (ostream & os, const Honghua & ghh)
26 {
27 os << ghh._ghh;
28 return os;
29 }
30
31 #endif // end of _20060816_OPERATOR_GHH_
4. 任何时候都不使用using namespace 声明!这是只需要修改20060816_operator.cxx文件如下:
2 #include " 20060816_operator.h "
3 int main( int argc, char * argv[])
4 {
5 // const string GHH("GuoHonghua");
6 const std:: string GHH( " GuoHonghua " );
7 Honghua ghh(GHH);
8 // cout << ghh << endl;
9 std::cout << ghh << std::endl;
10 return 0 ;
11 }
体会:
名字空间本来就是为了解决名字冲突问题而引入,以使标准库不受外界影响。在这个意义上来说,using namespace std;不是可以随意使用的语句,应该考虑到它的位置对程序的可能影响,而最彻底的杜绝错误的解决办法是在任何时候任何情况下都不使用此语句!