引言
假设我们有这样的类:
1 class A{ 2 public: 3 A(int num = 0, int den = 1) {}; 4 int num() const; 5 int den() const; 6 const A operator* (const A& rhs) const; 7 };
在做乘法时,我们可以采用以下的操作:
1 A a0(1, 2); 2 A a1(1, 3); 3 4 A match = a0 * a1; // 同类型相乘 5 match = match * a0; // 同类型相乘
上述操作是完全木有问题的,那么如果我们想实现跨类型相乘应该怎么做呢?
于是我们开始尝试这样来操作
1 match = a0 * 2; // OK match = a0.operator * 2 2 match = 2 * a0; // Error match = 2.operator * a0
是的,a0是一个包涵了operator*函数的class的对象,所以编译调用此函数。然而2却没有相应的class,也就没有相对应的operator*函数。
而上面成功的操作中,实际上调用了隐式转换函数,在编译器看来,实际执行的操作为:
1 const A temp(2); // 基于2建立一个临时对象 2 match = a0 * temp; // 等同于a0.operator * (temp);
这时如果我们将A的构造函数换成explicit函数,那么上述任何一种情况都不能进行隐式转换,也就没有任何一个语句可以编译通过。
让我们再深挖一些,为什么 match = 2 * a0;就不能通过隐式转换来完成呢?
答案是:只有当参数被列于参数列内,这个参数才是隐式转换的合格参与者。地位相当于”被调用的成员函数所属的那个对象“--即this对象的隐喻参数,不会是合格的参与者。这就是为什么第一次编译通过,而第二次编译不通过的原因:第一次调用伴随着一个放在参数列内的参数,而第二次调用则否。
时间: 2024-10-03 14:00:37