引言

假设我们有这样的类:

 class A{
public:
A(int num = , int den = ) {};
int num() const;
int den() const;
const A operator* (const A& rhs) const;
};

在做乘法时,我们可以采用以下的操作:

     A a0(, );
A a1(, ); A match = a0 * a1; // 同类型相乘
match = match * a0; // 同类型相乘

上述操作是完全木有问题的,那么如果我们想实现跨类型相乘应该怎么做呢?

于是我们开始尝试这样来操作

     match = a0 * ;       // OK        match = a0.operator * 2
match = * a0; // Error match = 2.operator * a0

是的,a0是一个包涵了operator*函数的class的对象,所以编译调用此函数。然而2却没有相应的class,也就没有相对应的operator*函数。

而上面成功的操作中,实际上调用了隐式转换函数,在编译器看来,实际执行的操作为:

 const A temp();     // 基于2建立一个临时对象
match = a0 * temp; // 等同于a0.operator * (temp);

这时如果我们将A的构造函数换成explicit函数,那么上述任何一种情况都不能进行隐式转换,也就没有任何一个语句可以编译通过。

让我们再深挖一些,为什么 match = 2 * a0;就不能通过隐式转换来完成呢?

答案是:只有当参数被列于参数列内,这个参数才是隐式转换的合格参与者。地位相当于”被调用的成员函数所属的那个对象“--即this对象的隐喻参数,不会是合格的参与者。这就是为什么第一次编译通过,而第二次编译不通过的原因:第一次调用伴随着一个放在参数列内的参数,而第二次调用则否。

一、使用non-member函数

如果我们一定要实现跨类型相乘,可以使用non-member来解决。

 class A{
public:
A(int num = , int den = ) {};
int num() const;
int den() const;
};
const A operator* (const A& lhs, const A& rhs) {
return A(lhs.num() * rhs.num(),
lhs.den() * rhs.den());
}

在这种情况下,下面的任意一种情况都可以实现:

     A a0(, );
A a1(, ); A match = a0 * a1;
match = match * a0; match = a0 * ;
match = * a0;

◆总结

如果你需要为某个函数的所有参数(包含被this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member。

[Effective C++ --024]若所有参数皆需类型转换,请为此采用non-member函数的更多相关文章

  1. 若所有的参数皆需要类型转换——请为此采用non-member函数

    若所有的参数皆需要类型转换--请为此采用non-member函数 经常使用C++的程序猿(希望更多的程序媛),一般不会同意让classes支持类型转换,至于为什么,请看后续的博客.假如我们设计一个表示 ...

  2. Effective C++ -----条款24:若所有参数皆需类型转换,请为此采用non-member函数

    如果你需要为某个函数的所有参数(包括被this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member.

  3. [EffectiveC++]item24:若所有参数皆需类型转换,请为此采用non-member函数

    Declare non-member functions when type conversions should apply to all parameters. 104页 只有当参数被列于参数列( ...

  4. 【24】若所有参数皆需类型转换,请为此采用non-members函数

    1.令class支持隐式类型转换,往往是个糟糕的主意.但有些情况是合理的,比如数值类型.考虑,有理数Rational有分子,分母两个字段,缺省参数值为0,1.Ration a = 2;我们期望构造一个 ...

  5. 读书笔记_Effective_C++_条款二十四: 若所有参数皆需类型转换,请为此采用non-member函数

    class A { private: int a; public: A(int x) :a(x){} A operator*(const A& x) { return A(a*x.a); } ...

  6. 条款24:若所有参数皆需要类型转换,请为此采用non-member函数(Declare non-member functions when type conversions should apply to all parameters)

    NOTE: 1.如果你需要为某个函数的所有参数(包括this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member.

  7. 条款24:如果所有的参数都需要类型转换,那么请为此采用non-member函数

    首先还是下面这个class; class Rational{ public: Rational(, ); int numurator() const; int denominator() const; ...

  8. 对setTimeout()第一个参数是字串的深入理解以及eval函数的理解

    <script language="javascript" type="text/javascript"> var a=1; setTimeout( ...

  9. Effective C++ 之 Item 6 : 若不想使用编译器自动生成的函数,就该明确拒绝

    Effective C++ chapter 2. 构造 / 析构 / 赋值运算 (Constructors, Destructors, and Assignment Operators) Item 6 ...

随机推荐

  1. [ahu 1248] NBA Finals

    NBA Finals Time Limit: 1000 ms   Case Time Limit: 1000 ms   Memory Limit: 64 MBTotal Submission: 251 ...

  2. 解决android手机sd卡安装pak后直接打开,按home键异常问题

    if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { finish(); return; }

  3. 【jQuery日期处理】两个时间大小的比较

    function checkEndTime(){ var startTime=$("#startTime").val(); var start=new Date(startTime ...

  4. 一个可能是pip的一个BUG

    今天重新安装了Python,把Python的安装位置改为 D:\Program Files\Python\Python34\ 用pip 安装 Django 的时候出现一下错误 >pip inst ...

  5. [Bhatia.Matrix Analysis.Solutions to Exercises and Problems]ExI.4.1

    Let $x,y,z$ be linearly independent vectors in $\scrH$. Find a necessary and sufficient condition th ...

  6. linux time命令参数--执行命令并计时

    [命令]time — 执行命令并计时 [格式]time [-p] command [arguments...] [说明] 执行命令行"command [arguments...]" ...

  7. HDU4578 Transformation 线段树

    这个题让我重新学习了加 乘 在区间的操作 题解:http://blog.csdn.net/guognib/article/details/25324025?utm_source=tuicool& ...

  8. JAVACC详解

    JavaCC(Java Compiler Compiler)是一个用JAVA开发的最受欢迎的语法分析生成器.这个分析生成器工具可以读取上下文无关且有着特殊意义的语法并把它转换成可以识别且匹配该语法的J ...

  9. [King.yue]Ext.net 弹出Windows窗体注意的事项

    页面的控件ID不能重复,否则会覆盖原控件.

  10. Flash 导出图片和声音

    命令文件 PolarBear_jsfl.zip Flash Professional 编辑器命令,用来导出 flash 库中的图片和声音 使用步骤: 1. 首先下载 PolarBear_jsfl.zi ...