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

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

2013-11-29 
std::string派生类实现operator const char*() const出错的问题,请帮我看看// 先包含头文件#include stri

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


// 先包含头文件
#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)”时
[解决办法]
引用:
Quote: 引用:

把 operator [] 改成这样。

template <typename T>
char operator []( T nIndex ) const


这不是编译器 bug,原来的写法 str[1] 会导致二义性,因为 [] 和 const char* 都适用,而且都存在隐式类型转换,无法决议。


太好了,你提供的方法解决了。

能否帮我解释一下具体原因“原来的写法 str[1] 会导致二义性,因为 [] 和 const char* 都适用”我实在找不出来在哪儿或哪些代码能让我明白这个问题。

另外6楼的方法也可以实现,但是就是不够优雅,对于用户来说代码直观性差了。

主楼的写法,编译器遇到 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 还是能算出来完全匹配比用户自定义转换优先级高,所以就不在抱怨了。就这样。
[解决办法]
引用:
顶一下,有没有大神帮忙解释一下为什么用了 
template <typename T>
char operator []( T nIndex ) const
模板函数就解决了呢?

有没有看我在6楼的解决方法?为什么要强调显示调用?
因为这里有一个自动转换的问题,str[]可以认为是CCrossString[],也可以认为是const char*(str)[]。
这才造成了二义性。强制转换很好用,但是尽可能不要隐式的自动转换,因为很容易造成你的这种问题。记得加explicit关键字。

热点排行