C++中类型转换与函数、运算符重载的问题(上)

来源:互联网 发布:海豚动态壁纸软件 编辑:程序博客网 时间:2024/06/07 03:09

最近在工作中遇到一个问题——编写一个C++类,拥有多个类,其中有一个类可以转换到其它所有的类,比如:

class A {};class B {};class C {public:    operator A() const { ... }    operator B() const { ... }};

另外,在全局还定义(重载)了几个函数:

void Func(const A &a, const A &b);void Func(const B &a, const B &b);
这时候,当用户调用Func函数,并传入C的对象的时候,例如:

C a, b;Func(a, b);
编译器会报出错:
test.cpp: In function ‘int main()’:test.cpp:23: error: call of overloaded ‘Func(C&, C&)’ is ambiguoustest.cpp:14: note: candidates are: void Func(const A&, const A&)test.cpp:17: note:                 void Func(const B&, const B&)
问题的根源在于,由于C定义了两个自定义类型转换函数,分别转换到A和B,在调用Func函数的时候,编译器也无法知道该调用哪个版本的Func函数,从而只能报错。

我们希望C的对象在调用其它函数的时候能够转换成A或者B的对象,但是在调用Func函数的时候,我们只希望它默认转换成A。刚开始我认为这个问题很好解决,只需要对代码略做调整,一个小时就能搞定。但是深入做起来以后,发现里面包含了很多C++的知识,而我平时都没有引起重视。通过解决这个问题也让我学到不少东西,让我对C++的类型转换和函数、运算符重载有了全新的认识。

我打算分上中下三篇文章分别介绍我想到的和学习到的一些解决方法。上篇主要介绍一些及其简单的方法。在某些情形下也许能够很简单的解决问题,但在我的实际工作中,由于各种各样的原因,无法使用。中篇将介绍一个比较复杂但基本可行的办法,虽然在某些情况下仍然存在一些问题。下篇我将给出我最后想到的一种解法,能够完整地解决这个问题。

解法一:明确类型转换
最简单和直接的解决办法是要求使用这个库的用户在调用这个函数地时候,明确地指明需要将class C转换成哪一个类:

Func((A)a, (A)b);
这种解法虽然简单而且直接,最重要的是它体现了一种良好的编程习惯,但是为了保证向上兼容性,我们不得不舍弃这种做法。因为我们无法要求用户因为这个改变,改掉所有现有的代码。

解法二:暴力添加新的重载函数

第二种方法也很直接——既然不能要求用户添加强制类型转换,我们就为C重载Func函数,然后再调用正确的版本:

void Func(const C &a, const C &b) {    Func((A)a, (A)b);}
同样地,这种解法也能解决问题。但是,这种解法也有其局限性。在我们的具体问题中,我们不光拥有C类,我们还拥有很多类似C这样的类,都能同时转换成A和B,例如:

class D {public:    operator A() const { ... }    operator B() const { ... }};
那么我们就需要为每个类重载一个这样的函数。而且我们希望支持这样的调用:

C cc;D dd;Func(cc, dd);
这样一来,我们就需要也重载:

void Func(const C &a, const D &b);void Func(const D &a, const C &b);
如果还有类似的很多类,例如E-Z,如果以后需要支持一个函数拥有三个或者跟多的参数,那么这样的排列组合就是天文数字。


原创粉丝点击