std::string派生类实现operator const char*() const出错的问题,请帮我看看

zhllxt 2013-11-27 07:05:49

// 先包含头文件
#include <string>
using namespace std;



class CCrossString : public string
{
public:
CCrossString(const char* lpsz) : string(lpsz) {};

char operator []( size_t nIndex ) const
{
return __super::operator[](nIndex);
}

operator const char*() const // 实现自动类型转换
{
return (const char*)__super::data();
}

};



//开始使用
CCrossString str("abc");
const char* lpsz = (const char*)str;// lpsz 的内容现在就是 "abc"
char c = str[1];//如果把此句注释掉就没有问题



如上,如果使用char c = str[1];这样的语句编译时就报错:

1>正在编译...
1>CrossString.cpp
1>f:\程序设计\vs2008\crossstring\crossstring\crossstring.cpp(60) : error C2666: “CCrossString::operator []”: 2 个重载有相似的转换
1> f:\程序设计\vs2008\crossstring\crossstring\crossstring.cpp(42): 可能是“char CCrossString::operator [](size_t) const”
1> 或 “内置 C++ operator[(const char *, int)”
1> 试图匹配参数列表“(CCrossString, int)”时
...全文
382 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
ri_aje 2013-11-28
  • 打赏
  • 举报
回复
引用 10 楼 zhllxt 的回复:
[quote=引用 9 楼 ri_aje 的回复:] 把 operator [] 改成这样。

template <typename T>
char operator []( T nIndex ) const
这不是编译器 bug,原来的写法 str[1] 会导致二义性,因为 [] 和 const char* 都适用,而且都存在隐式类型转换,无法决议。
太好了,你提供的方法解决了。 能否帮我解释一下具体原因“原来的写法 str[1] 会导致二义性,因为 [] 和 const char* 都适用”我实在找不出来在哪儿或哪些代码能让我明白这个问题。 另外6楼的方法也可以实现,但是就是不够优雅,对于用户来说代码直观性差了。[/quote] 主楼的写法,编译器遇到 str[1] 后发现 (1) 可以把 str 转换成一个 char const*,然后当指针用,因为使用的是你提供的 operator char const*,所以这种调用方法使用用户自定义转换。 (2) 可以调用 operator [] 完成操作,但是实参 1 的类型是 int,而形参的类型是 size_t,所以需要 int 到 size_t 的转换,这种调用方法使用隐式类型转换。 标准规定 (2) 比 (1) 的优先级高,所以重载解析应该选择 (2),程序编译执行应该都没有问题。 但 VS 家的编译器却出编译错误,所以这是编译器的 bug,我在 #9 关于这点说错了。 bug 就 bug 吧,VS 总是不太给力的。 #9 给的方法是一个临时的补救方案。 变成 template T 以后,编译器根据 str[1] 中的实参类型推导形参类型,因此 1 推出 int。 重要的是无论实参是什么类型,推导出的形参都必然具有相同的类型,所以 (2) 的调用中就不存在隐式类型转换的问题了,因此 (2) 变成完全匹配。然后看样子 VS 还是能算出来完全匹配比用户自定义转换优先级高,所以就不在抱怨了。就这样。
zhllxt 2013-11-28
  • 打赏
  • 举报
回复
顶一下,有没有大神帮忙解释一下为什么用了 template <typename T> char operator []( T nIndex ) const 模板函数就解决了呢?
zhllxt 2013-11-28
  • 打赏
  • 举报
回复
引用 9 楼 ri_aje 的回复:
把 operator [] 改成这样。

template <typename T>
char operator []( T nIndex ) const
这不是编译器 bug,原来的写法 str[1] 会导致二义性,因为 [] 和 const char* 都适用,而且都存在隐式类型转换,无法决议。
太好了,你提供的方法解决了。 能否帮我解释一下具体原因“原来的写法 str[1] 会导致二义性,因为 [] 和 const char* 都适用”我实在找不出来在哪儿或哪些代码能让我明白这个问题。 另外6楼的方法也可以实现,但是就是不够优雅,对于用户来说代码直观性差了。
ri_aje 2013-11-28
  • 打赏
  • 举报
回复
把 operator [] 改成这样。

template <typename T>
char operator []( T nIndex ) const
这不是编译器 bug,原来的写法 str[1] 会导致二义性,因为 [] 和 const char* 都适用,而且都存在隐式类型转换,无法决议。
zhllxt 2013-11-28
  • 打赏
  • 举报
回复
非常感谢两位的解答,明白了。 又进步了!!!
Adol1111 2013-11-28
  • 打赏
  • 举报
回复
12楼解释的很清楚了,但有的时候直接禁止隐式转换是最好的。 explicit刚刚去查了一下,C++11才允许使用,VS要2012以上才行。
Adol1111 2013-11-28
  • 打赏
  • 举报
回复
引用 11 楼 zhllxt 的回复:
顶一下,有没有大神帮忙解释一下为什么用了 template <typename T> char operator []( T nIndex ) const 模板函数就解决了呢?
有没有看我在6楼的解决方法?为什么要强调显示调用? 因为这里有一个自动转换的问题,str[]可以认为是CCrossString[],也可以认为是const char*(str)[]。 这才造成了二义性。强制转换很好用,但是尽可能不要隐式的自动转换,因为很容易造成你的这种问题。记得加explicit关键字。
Todd_Pointer 2013-11-27
  • 打赏
  • 举报
回复
感觉应该是编译器BUG, 换个编译器试试。 另外公开继承 std::string 确实算不上好主意,std::string* p = new CCrossString; delete p; 从语义上讲是有瑕疵的。
zhcosin 2013-11-27
  • 打赏
  • 举报
回复
最好你的类不要从 std::string 继承,因为 std::string 的析构函数不是虚函数,当然你保证你的类永远不会用 new 来创建对象,那倒也无所谓。
Adol1111 2013-11-27
  • 打赏
  • 举报
回复
你的这两个重载有冲突,改成下面这种就好了:
explicit operator const char*() const // 必须显示调用
{
	return (const char*)__super::data();
}
也可以在调用时显示调用:
char c = str.operator[](1);
dyw 2013-11-27
  • 打赏
  • 举报
回复
你知道std::string里为什么没有提供这个自动类型转换吗?
zhllxt 2013-11-27
  • 打赏
  • 举报
回复
我都已经派生成功了啊,而且除了上面的问题,其它全部正常啊。
Exaybachay 2013-11-27
  • 打赏
  • 举报
回复
std::string 是不能派生的
zhllxt 2013-11-27
  • 打赏
  • 举报
回复
已经重载了也不影响的,如果把 operator const char*() const 这个重载去掉再用char c = str[1];也没有问题,就是说operator const char*() const和char operator []( size_t nIndex ) const不能共存,不知道原因在哪儿,MFC的CString类这两个重载就是可以共存的。
ztenv 版主 2013-11-27
  • 打赏
  • 举报
回复
char operator []( size_t nIndex ) const 已经 重载了这个了吧?

64,636

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧