CSDN博客

img wingfiring

C++中为什么不允许通过返回类型重载函数的辩论

发表于2004/7/8 14:49:00  6934人阅读

分类: C/C++

2004-07-05 13:25:31 别逗了
问个问题:
1。C++中为什么不允许通过返回类型重载函数?
2。为什么不允许通过返回类型解析模板函数?

2004-07-05 14:47:55 完美废人
返回类型是一种可有可无的东西……

2004-07-05 16:41:23 完美废人
瞧见什么叫高手了吧

2004-07-05 18:32:46 别逗了
那operator type()怎么说?不是根据返回值判断调用那个函数的吗?

2004-07-05 18:34:49 完美废人
void f();
int f();
f(); //which one to go?

2004-07-05 18:35:18 别逗了
增加一条规则就是了。

2004-07-05 18:35:27 无锋之刃
啊哈!

2004-07-05 18:35:31 完美废人
怎么描述?

2004-07-05 18:35:53 完美废人
type-cast operators are individual functions, not the same one with diff return type

2004-07-05 18:39:11 别逗了
void f();
int f();
之间只是存在歧义,当出现歧义的时候,按照C++的习惯,制定一个最佳匹配规则。规则不行的时候,扩展语法, 调用形式: f() void;或者f() int;

2004-07-05 18:39:37 完美废人
手工确认调用哪个函数?那还要重载干吗?

2004-07-05 18:39:44 完美废人
而且

2004-07-05 18:39:57 无锋之刃
最佳匹配规则上说你这两个选择一样地好……

2004-07-05 18:39:58 完美废人
void f() 和 int f();,没有重载规则可以达到调用 void f();

2004-07-05 18:40:13 别逗了
那问题是,可以判别的时候,就不用指定了啊.

2004-07-05 18:40:32 无锋之刃
那问题是,没有办法 判别。

2004-07-05 18:40:39 完美废人
为了这么一点方便?我不如直接写 void f_void(); 和 int f_int(); 算了

2004-07-05 18:41:03 别逗了
那你放到模板里面怎么办?

2004-07-05 18:41:27 完美废人
拜托了大哥,尽量简化问题是每个程序员应尽的义务

2004-07-05 18:41:43 别逗了
调用形式作一个扩展不行?例如f() void;

2004-07-05 18:41:57 完美废人
f() void; 和 f(); 怎么区别?

2004-07-05 18:42:06 别逗了
指定返回值是void的f().

2004-07-05 18:42:15 完美废人
我直接 f(); 就会有二义性错误

2004-07-05 18:42:21 别逗了
对.

2004-07-05 18:42:23 完美废人
这样的语法,还不如不用重载

2004-07-05 18:42:43 无锋之刃
这是历史的倒退。

2004-07-05 18:42:52 别逗了
问题是,加了这个,对你以前的重载有影象吗?

2004-07-05 18:43:11 别逗了
你以前的代码规则照样起作用.

2004-07-05 18:43:57 别逗了
你完全可以不通过返回值重载函数---只有需要的人才会用到这个功能.

2004-07-05 18:44:11 别逗了
为什么就倒退了?

2004-07-05 18:44:25 完美废人
struct base
{
  virtual void f();
};
struct d:public base
{
  void f();
  int f();
};
base * p = new d;
p->f(); ??

2004-07-05 18:44:45 无锋之刃
编译器无法通过返回类型来判断应该调用哪个函数。链接器也是。

2004-07-05 18:45:20 别逗了
首先,你按照新的规则,定义了一对重载函数,却指望按照老的方式调用,当然不行.

2004-07-05 18:45:49 完美废人
如果没有 struct d,我的老规则完全适用

2004-07-05 18:45:51 无锋之刃
那什么是新的调用方式?

2004-07-05 18:45:52 别逗了
我的意思,增加了新的规则,你的老的重载方式,还是像以前一样工作.

2004-07-05 18:46:02 完美废人
除非你规定,所有的 void f(); 都必须改成 f() void; 这样调用

2004-07-05 18:46:07 别逗了
p->f() void;
或者

2004-07-05 18:46:12 别逗了
p->f() int;

2004-07-05 18:46:26 完美废人
struct S
{
  void f(); //how to call?
};

2004-07-05 18:46:30 无锋之刃
那我还不如写p->f_int()呢。搞那么复杂。

2004-07-05 18:46:41 完美废人
这个重载完全没有意义

2004-07-05 18:47:07 别逗了
好,我举个有意义的例子给你.

2004-07-05 18:48:20 完美废人
plz

2004-07-05 18:48:27 别逗了
max(T1& lhs, T2& rhs)
{
  //应该返回什么类型?
}
int i = max(2, 3.3);
double d = max(2, 3.3);
 

2004-07-05 18:48:51 别逗了
这是内部类型,可以互相转换,如果是自定义类型呢?

2004-07-05 18:49:05 别逗了
max应该返回什么类型?

2004-07-05 18:49:08 完美废人
自定义类型怎么能进行比较?

2004-07-05 18:49:17 完美废人
如果能比较,就应该能转化

2004-07-05 18:49:27 别逗了
我的自定义类型定了了less不可以阿?

2004-07-05 18:49:39 完美废人
你试试看。

2004-07-05 18:51:17 别逗了
例如我定义了dec类型和money类型。返回值需要做转换,转换可能丢失精度。如果不需要转换,那就没有这个问题。

2004-07-05 18:52:41 完美废人
所以你有
dec max(const dec &, const money &);

money max(const dec &, const money &): ?

2004-07-05 18:54:00 完美废人
1、建议你看看 C++0x 的 typeof
2、不论什么时候,重载决断是编译器的,不存在动态联编,所以根据返回值重载不切实际。

2004-07-05 18:54:21 别逗了
对。我的money类型是定点数,在进行数学运算的时候,有时候需要转换成dec类型,以防止中间运算过程的精度误差。算完了,还要转换回来。

2004-07-05 18:54:30 完美废人
2、不论什么时候,重载决断是编译器的,不存在动态联编,所以根据返回值重载不切实际。
 

2004-07-05 18:55:03 别逗了
呵呵,我要的就是决断是编译器的。

2004-07-05 18:55:07 完美废人
这个地方,你不如用 enum 好了。

2004-07-05 18:55:13 完美废人
抱歉,我是说 union

2004-07-05 18:55:28 别逗了
union和我的问题有啥关系?

2004-07-05 18:55:56 完美废人
typedef union {dec, money} rt_t;
rt_t max (const money &, const dec &);

2004-07-05 18:56:36 别逗了
靠,这不行的,这可真的运行期判决了。

2004-07-05 18:56:37 完美废人
对 money 和 dec 设计用 NullObject 作为默认值,可以用来检查 rt_t 的值

2004-07-05 18:56:50 完美废人
你不靠运行期决断,返回值就不存在意义。

2004-07-05 18:57:21 完美废人
money m;
dec d;
infile >> m >> d;
max(m, d); ??

2004-07-05 18:57:34 别逗了
谁说得?先确定一下,你不反对我要返回不同类型的数据了吧?

2004-07-05 18:57:44 完美废人
反对。

2004-07-05 18:57:56 完美废人
强烈反对用 union 这么变态的东西

2004-07-05 18:58:02 别逗了
好,那一个个问题来。

2004-07-05 18:58:10 benbear
强烈反对废人此观点

2004-07-05 18:58:21 别逗了
首先,我才不要返回union 。

2004-07-05 18:58:21 完美废人
我有一个很好的解决办法

2004-07-05 18:58:31 完美废人
想不想听?

2004-07-05 18:58:38 别逗了
我要返回的就是money或者是dec

2004-07-05 18:58:56 完美废人
std::pair 作为返回好了,哈哈。

2004-07-05 18:59:43 benbear
你试过
dec max(const dec &, const money &);

money max(const dec &, const money &):
能通过编译吗?

2004-07-05 18:59:47 别逗了
一样没用。你怎么知道返回值是什么类型?返回两个?那你怎么知道该用那个?

2004-07-05 19:00:06 完美废人
把不是返回值的一个指针作为 0

2004-07-05 19:00:17 完美废人
这是为什么我用指针而不是引用的原因

2004-07-05 19:00:22 完美废人
指针有 NullObject

2004-07-05 19:00:26 别逗了
我知道不能,所以我才不满意C++强加的限制。

2004-07-05 19:01:01 别逗了
越来越垃圾的设计了。[shake]

2004-07-05 19:01:12 完美废人
总比越来越垃圾的语言好[:D]

2004-07-05 19:01:28 完美废人
荼毒你一个,幸福俺大家

2004-07-05 19:01:32 别逗了
怎么垃圾了,我说得新特性你可以不用啊。

2004-07-05 19:01:46 完美废人
那么你告诉我,怎么调用 basd::virtual void f(); ??

2004-07-05 19:02:22 完美废人
我真的可以对一个
void func (base * p)
{
  p->func(); //不是 p->func() void; ?
}

2004-07-05 19:02:47 完美废人
没有什么东西是没有代价的。

2004-07-05 19:03:21 别逗了
你不是不用嘛,干吗要通过返回值重载?只要你不仅仅通过返回值重载(这是现状),就不必知道新特性。但是,你需要仅仅通过返回值重载,你就需要新特性。

2004-07-05 19:03:41 完美废人
我当然不用!但是我不能保证从我的类派生的家伙们不用!

2004-07-05 19:04:07 完美废人
作为一个接口基类,我必须把一切该死的可能性都考虑进去

2004-07-05 19:04:35 别逗了
OK.那么,、先确认一点:新特性对既有的代码,不需要修改,同意不?

2004-07-05 19:04:52 完美废人
不同意

2004-07-05 19:05:03 别逗了
那你举例反对。

2004-07-05 19:05:45 完美废人
struct Base
{
virtual void fun();
};

void f(const Base * p)
{
  p->fun(); //你要我抄多少遍?
}

2004-07-05 19:07:29 别逗了
很显然,这是调用void fun()啊。现有规则就能解决。如果派生类定义了同名的,而类型不同,那就是同名覆盖,而不是重载。

2004-07-05 19:08:11 完美废人
好,某个 newbie 写了
struct Derived : public Base
{
  virtual void fun();
  virtual int fun();
};
如何??

2004-07-05 19:08:31 别逗了
这个在现有规则下合法吗?

2004-07-05 19:09:00 完美废人
我的基类是旧规则的,但是这个 newbie 是学习新规则长大的,如何?旧的代码已经不能通用了!

2004-07-05 19:09:48 别逗了
靠,newbie写的是新代码!他既没有遵守旧规则,也没有遵守新规则!

2004-07-05 19:10:09 完美废人
他为什么没有遵守新规则?很漂亮的 rt-overload

2004-07-05 19:10:32 别逗了
让我想想。

2004-07-05 19:11:57 完美废人
:)恭候。

2004-07-05 19:14:17 别逗了
OK。这里只能调用void fun(),因为,virtual void fun();
  virtual int fun();是两个函数。而Base当中根本就不认识virtual int fun();所以,你老的代码f(const Base * p)
只有一种选择,就是原来的那一个。
 

2004-07-05 19:14:47 别逗了
所以,这里没有任何问题。[:D]

2004-07-05 19:15:05 无锋之刃
[?]

2004-07-05 19:15:15 完美废人
呵呵,有道理。

2004-07-05 19:15:28 完美废人
刀子,替我砍!

2004-07-05 19:15:45 无锋之刃
你去弄个砧板来

2004-07-05 19:15:48 别逗了
好啊,继续,我接着。

2004-07-05 19:16:34 完美废人
那么,如果 struct Base 放在新规则下,我就必须写 p->fun() void; 了?

2004-07-05 19:18:12 别逗了
不必。只有在老规则不能分辨的时候才需要这样写。
例如:
long f(int);
char f(char);
不需要写成f(10) int;

2004-07-05 19:19:10 完美废人
struct Base
{ virtual void fun(); };
struct Derived : public Base
{ virtual int fun(); };
算是隐藏?

2004-07-05 19:19:30 完美废人
这个在现有模式下是怎么处理的?

2004-07-05 19:19:33 别逗了
但是也有部分地方会有问题,就是没有一个是匹配的,但是存在两个同样优先级的转换时。

2004-07-05 19:19:50 完美废人
这个从来都存在问题……无奈了

2004-07-05 19:20:03 完美废人
我上次写那个 bi_map,都差点放弃重载了

2004-07-05 19:20:37 别逗了
1。现有模式不能只通过返回值区分重载。2。如果你的参数不同,那么,这两个函数覆盖。

2004-07-05 19:21:23 完美废人
都是 (void) 的时候,发生的是覆盖、修改接口、还是??

2004-07-05 19:21:34 别逗了
覆盖。

2004-07-05 19:21:44 别逗了
错了。

2004-07-05 19:21:50 完美废人
到底是……?

2004-07-05 19:21:52 别逗了
怎么都是void?

2004-07-05 19:22:11 完美废人
int f(void); 和 派生类的 void f(void); 或者相反。

2004-07-05 19:22:21 无锋之刃
你们在讨论虾米……

2004-07-05 19:22:22 别逗了
是这样:
覆盖

2004-07-05 19:22:42 完美废人
这个东西我是没法明白了……刀子或者鸡丁还有希望:(

2004-07-05 19:22:52 别逗了
倒!

2004-07-05 19:23:01 无锋之刃
《EC》上说“绝对不要重新定义继承而来的非虚函数”……

2004-07-05 19:23:17 别逗了
是啊。

2004-07-05 19:23:23 完美废人
struct Base
{ virtual void fun(); };
struct Derived : public Base
{ virtual int fun(); };

2004-07-05 19:23:26 无锋之刃
那……

2004-07-05 19:23:30 完美废人
struct Base
{ virtual void fun(); };
struct Derived : public Base
{ virtual int fun(); };

2004-07-05 19:23:30 别逗了
但是,语言则要考虑到。

2004-07-05 19:23:34 完美废人
两个函数签名相同啊,怎么会是覆盖的?

2004-07-05 19:24:00 无锋之刃
返回值类型是不会被Name-mangling机制处理的。

2004-07-05 19:24:18 完美废人
所以应是一般的派生类重写而已

2004-07-05 19:24:23 别逗了
晕倒,签名规则不可以变啊?况且,签名规则根本就是和编译没太大关系得,连接系统关系比较大而以。

2004-07-05 19:24:38 完美废人
我现在是说传统 C++……

2004-07-05 19:24:45 无锋之刃
你把你的想法提交C++ Standard Commitee,也许有可能……

2004-07-05 19:24:46 完美废人
不了解过去就无法预测将来

2004-07-05 19:26:06 别逗了
我好像在那里看到过说为什么不能通过返回值重载的,但是,我实在是想不起来任何线索了。

2004-07-05 19:26:24 完美废人
别逗了:这两个函数签名相同,不可能是覆盖……

 

 

2004-07-05 19:26:49 无锋之刃
也不可能是重载,因为参数列表一样。

2004-07-05 19:27:05 完美废人
本来就不可能,因为是在不同的 class scope

2004-07-05 19:27:14 完美废人
所以只能是重写了。

2004-07-05 19:27:32 无锋之刃
重定义。

2004-07-05 19:27:33 别逗了
函数签名不包括返回值?那dump出来的dll中怎么解析我的返回值类型的?

2004-07-05 19:27:59 完美废人
dump 出来的 dll 还支持 const char * 到函数的映射呢……

2004-07-05 19:29:41 别逗了
不要搞,我问你:int CppUnit::CompilerOutputter::wrapColumn(void)
Name-mangling之后怎么知道返回值是int而不是void的?

2004-07-05 19:29:52 完美废人
不知道。

2004-07-05 19:30:09 完美废人
返回值和 name mangling 无关

2004-07-05 19:31:09 别逗了
int CppUnit::CompilerOutputter::wrapColumn(void)
是我用depends从dll中导出的函数名。
这是C函数名:
?wrapColumn@CompilerOutputter@CppUnit@@QBEHXZ
你是这里面没有返回值信息?

2004-07-05 19:31:29 完美废人
我没看到 int 啊

2004-07-05 19:31:44 别逗了
那时你不知道怎么解码。

2004-07-05 19:32:11 完美废人
呵呵:)这是一句没有说服力的反驳

2004-07-05 19:32:11 无锋之刃
在C中调用C++的函数,要在C++代码中使用extern "C"来禁止重载的……

2004-07-05 19:33:05 别逗了
晕倒,我刚才的两个名字就是同一个,只不过depends能够?wrapColumn@CompilerOutputter@CppUnit@@QBEHXZ解码成int CppUnit::CompilerOutputter::wrapColumn(void)这样可以读的格式。

2004-07-05 19:33:26 无锋之刃
那也只是凑巧……

2004-07-05 19:33:36 完美废人
呵呵~这是用结论逆推理论。

2004-07-05 19:33:58 别逗了
什么凑巧,C++的dll全都是这样的,自己可用depends去看。

2004-07-05 19:34:30 无锋之刃
别在Dll中使用太多重载,不然会死得很惨的。

2004-07-05 19:34:34 别逗了
我的意思是:Name-mangling不过是一种实作手段而以。

2004-07-05 19:34:48 完美废人
我没有 depends。逆试试
struct { int f();}
struct { void f();}
有没有区别

2004-07-05 19:35:07 无锋之刃
但是为什么编译器厂商都没有把你想的实作出来呢?

2004-07-05 19:35:23 别逗了
你不是用vc的吗?怎么没有depends?

2004-07-05 19:35:29 完美废人
不知道:(

2004-07-05 19:35:52 别逗了
depends.exe没有?晕倒!

2004-07-05 19:36:11 完美废人
好像没装 vc-tools 的说……

2004-07-05 19:36:13 无锋之刃
C++编译出的Dll在Console下怎么调用?

2004-07-05 19:36:24 完美废人
LoadLibrary

2004-07-05 19:36:30 别逗了
可以得。

2004-07-05 19:36:33 无锋之刃
又一个API……

2004-07-05 19:36:40 无锋之刃
[:8]

2004-07-05 19:36:55 别逗了
C编译出的dll难道不需要?

2004-07-05 19:37:07 完美废人
我正在看 CreateRemoteThread,居然被别逗了老兄拉来侃这个……

2004-07-05 19:37:28 别逗了
玩那个干吗?

2004-07-05 19:37:41 完美废人
为了他*妈*的造福人民,调试病毒用。

2004-07-05 19:38:01 无锋之刃
传说中尝遍百草的废人……

...

0 0

相关博文

我的热门文章

img
取 消
img