关于内置操作符、重载和模板函数

xueweizhong 2003-11-10 04:45:45
加精
前几天看到这里的一个帖子,想回答来着,却已经结贴了。
这里重新提出来,换个角度讨论一下,呵呵:
struct A
{
int m_i;
};
typedef A* A_ptr;

struct B
{
A_ptr m_aptr;
operator A_ptr ()
{
return m_aptr;
}
};

int main()
{
B b;
(*b).i;
^^^^^^^ // ---#1
}

提问的人问#1处发生了什么隐式转换的问题。

下面是我的问题:

这里有几点比较疑惑的地方,提出来大家交流一下:
(1) *b导致operator* 函数的overload resolution
那么编译器是怎么找到合适的operator*的?
(2) 如果内置的operator*用模板实现,是否更合适:
template <typename T>
T& operator *(T*);
(3) 内置的operator *对任何类型T都有
T& operator* (T*); --------#2
函数原型。
但代表无穷多个函数的函数原型#2却并非
函数模板。
(4) (2)和(3)细微差别是什么?
(3)代表着重载,
(2)首先需要模板推导,推导完成后只剩下一个版本。
所以感觉上(2)比较干净。

(5) 一个“不可能的”回答问题:
比如
struct Foo
{
operator int* ();
operator char* ();
operator A_ptr ();
};
Foo foo;
将导致*foo的任何使用都是歧义的。

struct Foo
{
template <typename T>
operator T* ();
};
Foo foo;
A* ptr = *foo; ptr->m_i; 是合法的。
而(*foo).m_i感觉上应该仍旧非法。

...全文
152 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
LinuxPanther 2003-12-11
  • 打赏
  • 举报
回复
我要保存,可是它要等入。
mufengqing 2003-12-02
  • 打赏
  • 举报
回复
mark
mfcer2 2003-11-28
  • 打赏
  • 举报
回复
mark
aflyinghorse 2003-11-20
  • 打赏
  • 举报
回复
呵呵,你手上的C++编译器还真不少。既然你已经验证过,那就应该没问题。

在C++ Primer15.10这一节有对这个问题的说明。
如果类定义了互相转换的函数,二义性可能会出现。
可以通过显示调用转换函数,解决这种二义性问题
如:Target target = Source().operator target();
xueweizhong 2003-11-20
  • 打赏
  • 举报
回复
>to aflyinghorse() :
我觉得这段陈述中的look for ..., look for ..., then look for ...template ..
应该没有优先级关系。作者应该并不强调这点,只是这么陈述罢了。

而且如果真要说清楚的化,应该说,
如果没有的话..., 同时应该说如果有的话....

现在作者知识就一个例子如此陈述而已。

g++的确接受了这个例子,也的确选择了构造函数。
但是CC,VC, CBC, COMEAUCOMPUTING都否定了,应该没问题。
JerKii 2003-11-19
  • 打赏
  • 举报
回复
还有一种情况的使用可以使我们的程序更具灵活性:
class C {
public:
int m_i;
public:
void testFn(C*);
operator C*(){return this;};
};

void C::testFn(C* ptr){
ptr->m_i = 239;
}

使用:
C c;
c.testFn(c); <<< 该句的调用会自动触发operator C*()的执行,如果没有定义该操作符,则编译出错
c.testFn(&c); << 该句不会执行operator C*()

JerKii
aflyinghorse 2003-11-19
  • 打赏
  • 举报
回复
Item 28 smart pointers:
They look for a single-argument constructor (see Item 5) in the SmartPtr<MusicProduct> class that takes a SmartPtr<Cassette>, but they find none. They look for an implicit type conversion operator in the SmartPtr<Cassette> class that yields a SmartPtr<MusicProduct> class, but that search also fails. They then look for a member function template they can instantiate to yield one of these functions.
aflyinghorse 2003-11-19
  • 打赏
  • 举报
回复
#include <iostream>
using namespace std;

struct Source;
struct Target
{
Target(){};
Target(Source const &){cout<<"ctor";}; // non-const reference
};

struct Source
{
operator Target()
{cout<<"operator";return Target();};
};


int main()
{
Target target = Source();
getchar();
}
这个程序在dev-cpp4.9.8.4下会有这样的warning: choosing `Source::operator Target()' over `Target::Target(const Source&)'
for conversion from `Source' to `Target'
because conversion sequence for the argument
is better
xueweizhong 2003-11-19
  • 打赏
  • 举报
回复
>to aflyinghorse()
就让我再相信Scott Meyer一下,请告诉我
more effective c++上的哪一条说了这种情况?
xueweizhong 2003-11-19
  • 打赏
  • 举报
回复
>to aflyinghorse()
把你的代码贴一下。

有一种情况下,构造函数将不被考虑:
struct Source;
struct Target
{
Target(Source&); // non-const reference
};

struct Source
{
operator Target () const;
};

Target target = Source();

因为构造函数中的Source&参数不能绑定到r-value, 所以
就只能考虑转换函数了。
aflyinghorse 2003-11-18
  • 打赏
  • 举报
回复
如果同时提供了这两种:
由于这两种都是用户定义转换,不可以进行比较,
我也觉得应该这样。

但我在dev-cpp下试,结果是选择转换函数,而且给出一个警告,意思是说转换函数是比构造函数更好的选择,

而且看more effective c++上说会先考虑单参数构造函数,然后是转换函数。

不知标准怎么定义的,我还是认为如果同时提供了这两种,应该是两个转换一样好,导致编译错误。
Wolf0403 2003-11-16
  • 打赏
  • 举报
回复
郁闷啊。。。被 VC 的语言扩展耍了一把
xueweizhong 2003-11-16
  • 打赏
  • 举报
回复
呵呵,如果同时提供了这两种:
由于这两种都是用户定义转换,不可以进行比较,
将永远导致歧义性。
^^^^
>to Wolf0403(完美废人)
还需要再考虑一下...
Wolf0403 2003-11-16
  • 打赏
  • 举报
回复
转换操作符还是调用了 Target 的构造函数,而且——
Source s;
Target t = s;
如果 Source 提供了转换操作符,编译器优先调用这个转换操作符,结果是比没有这个转换操作符的情况下多生成一个 Target 的临时对象
xueweizhong 2003-11-14
  • 打赏
  • 举报
回复
自定义转换有两种:
1:由构造函数定义:
必须是单参数或者
多参数,但后面的参数都有缺省值:

且构造函数没有explicit修饰符。

struct Target
{
Target(Source src);
// or Target(Source src, Other1 other1=default1, Other2 other2=default2)
};
Source source;
Target target = source;

2: 转换操作符
struct Source
{
operator Target ();
};
Source source;
Target target = source;

第一种转换由Target提供.
第一种转换由Source提供.
laomai 2003-11-14
  • 打赏
  • 举报
回复
请教mmlymlymly(mly) :
user-defined conversion的语法形式是什么?您能给出一个具体的例子吗?

darcymei 2003-11-11
  • 打赏
  • 举报
回复
operator int* ();是重载*操作符吗?不是吧,这是用户定义转化类型
即可将类对象强制转化成int *的操作;
*b在编译器看来是强制转化解引用(不可,因为b不是指针)或强制转化成某种指针,所以就选择强制转换成 A_ptr。
这样的话(5)也很好解释, A* ptr = *foo;编译器会默认调用 (A_ptr),就像int i=double d;
darcymei 2003-11-11
  • 打赏
  • 举报
回复
但是也是有代价的,应该不能是虚拟函数了吧!(上课,来不及了写个试试,感觉不可以)
xueweizhong 2003-11-11
  • 打赏
  • 举报
回复
>to mmly...
呵呵,说到点子上了。
再帮我看看_overload_宏那一贴。

我说明一下,我明白这里发生了什么。

只是想从结果里上探讨一下:
模板函数比函数重载“干净”很多这个东东。
darcymei 2003-11-11
  • 打赏
  • 举报
回复
上面写的有点问题
全局重载operator* 是 return_value_type ::operator * (const A * &);
内部重载operator* 是 return_value_type A::oprator * ();

加载更多回复(9)

64,646

社区成员

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

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