首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

请问:关于操作符重载,隐藏与隐式转换的困惑

2012-08-01 
请教:关于操作符重载,隐藏与隐式转换的困惑有个问题有点疑惑,请教下大家:且看一下以下这段代码C/C++ code#

请教:关于操作符重载,隐藏与隐式转换的困惑
有个问题有点疑惑,请教下大家:

且看一下以下这段代码

C/C++ code
#include <string>class CMyString : public std::string{public:    CMyString ();    /*explicit */CMyString (const char *pszStr); [0]    /*explicit */CMyString (std::string str);    [0]    ~CMyString(void);    CMyString operator += (const CMyString &rStr);    CMyString operator + (const CMyString &rStr);};CMyString::CMyString(){}CMyString::CMyString( const char *pszStr ){}CMyString::CMyString( std::string str ){}CMyString::~CMyString( void ){}CMyString CMyString::operator+=( const CMyString &rStr ){}CMyString CMyString::operator+( const CMyString &rStr ){}int main(int argc, char* argv[]){    CMyString myStr;    char szTest[] = "test";    myStr += szTest;    // [1]ok    CMyString* pStr = &myStr;    pStr->operator + (szTest);    // [2]ok 隐藏?    myStr + szTest;    // [3] error//      error C2666: 'CMyString::operator +' : 2 overloads have similar conversions//      could be 'CMyString CMyString::operator +(const CMyString &)'//             or       'std::basic_string<_Elem,_Traits,_Ax> std::operator +<char,std::char_traits<char>,std::allocator<_Ty>>(const std::basic_string<_Elem,_Traits,_Ax> &,const char *)' [found using argument-dependent lookup]//             with//                 [//                         _Elem=char,//                             _Traits=std::char_traits<char>,//                             _Ax=std::allocator<char>,//                             _Ty=char//                         ]//             while trying to match the argument list '(CMyString, char [5])'    return 0;}


编译器是vs2008,
从提示上看,编译器是弄不清,这里是调用
  1. 调用std::string::operator+ 
 还是 2. 先将 const char* 隐式转换成CMyString,然后调用 CMyString operator + 

我的疑问是

a. 如果是这样,为什么[1]处,同样的情况,换成operator +=,就不报错,为什么编译器不疑惑调用的是
  1. std::string::operator +=
还是 2. CMyString::operator+=

难道说,编译器真正在乎的是这个时候他决定不了+完以后的类型所以才报错?


b. [2]处能正常过编译,是因为隐藏机制在其作用么?
  难道说隐藏是只对指针来说的,直接通过对象来调用就没这个说法?

c. 或者说,之所以[1]可以,[3]不行,vs2008的编译器的提示有点误导作用,本质不是决定不了调用哪个函数,而是无法先决定转换方法,因为同样的代码,我用DevC++编译,出来的结果是
ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: 

网上搜索了下,这个似乎也是发生于类似情况,决定不了使用哪个转换的时候。

d. 既然问了,顺便再夹带一点东西,

http://www.cppblog.com/elprup/archive/2010/05/05/114491.html
  这篇文章中的代码
C/C++ code
#include <iostream>#include <cstdlib>using namespace std;class X{public:    X(int xx):x(xx){}    int x;};class Y{public:    Y(X xx):y(xx.x){}    int y;};void f(Y){}int main(){//======case 1======    X x(2);    f(x); //ok    f(X(2));//ok//======case 2======    f(2);  //error:conversion from `int' to non-scalar type `Y' requested     system("PAUSE");    return 0;}


作者的对这个的解释是,隐式转化只能转换一次,这个是否是有标准依据的?

[解决办法]
看了一下, 解释不出原因, 歧义在于两个构造函数, 为什么=冲突+=不冲突呢, 不知道.
[解决办法]
先将 const char* 隐式转换成CMyString,然后调用 CMyString operator + =
因为你没有重载 CMyString operator + =(const char*)

至于myStr + szTest存在2中路径 
1.const char* => CMyString 然后operator +
2.const char* =>string =>CMyString 然后operator+
[解决办法]
个人感觉应该是缺少operator+(char[]),因为+的运算太多了。。。
------解决方案--------------------


我同意6楼的说法
[解决办法]
a. [1] 处 szTest 隐式转化为 CMyString,然后调用 CMyString::operator+=(CMyString&)。
b. [2] 处采用 qualified name lookup,直接找到 CMyString::operator+,std::string::operator+ 压根没进入重载集,因此不形成二义性。
c. [3] 处调用的 + 操作符再用 unqualified name lookup 以及 argument dependent name lookup,后者找到CMyString::operator+ 和 std::string::operator+ 两个候选函数。重载解析无法决议那个调用更合适,因为 CMyString::operator+ 存在 CMyString (const char *pszStr) 的隐式转换,而 std::string::operator+ 存在 CMyString& -> std::string& 的隐式转换。这也是 DevC++ 抱怨的东西,两条路都行,导致二义性,无法决议调用那个函数。[3] 和 [2] 不矛盾,你把 [3] 改成这样,就和 [2] 一样了, myStr.operator + (szTest),这时候一样是 qualified name lookup,一样没有二义性,因为 std::string::operator+ 不可见。
d. f(2) 调用是错误的,不过不是因为隐式转换只能发生一次,而是因为在一个隐式转换序列中,用户自定义转换至多只能出现一次。f(2) 的调用要求 2 -> X(2) -> Y(X(2)),有两次自定义转换。
[解决办法]

探讨

引用:

a. [1] 处 szTest 隐式转化为 CMyString,然后调用 CMyString::operator+=(CMyString&amp;amp;)。
b. [2] 处采用 qualified name lookup,直接找到 CMyString::operator+,std::string::operator+ 压根没进入重载集,因此不形成二义性。
……
[1]处 myStr += szTest; 是否也是 unqualified name lookup,如果是的话,为什么不会产生
CMyString::operator+=(CMyString&) 和 std::string::operator+= (const char* pszStr) 的矛盾

热点排行