条款24 若所有参数皆需类型转换,请为此采用non-member函数
来源:互联网 发布:美豆数据 编辑:程序博客网 时间:2024/05/22 04:38
总结:
如果你需要在一个函数的所有参数(包括被 this 指针所指向的那个)上使用类型转换,这个函数必须是一个非成员。
让一个类支持隐式类型转换通常是一个不好的主意。当然,这条规则有一些例外:在创建数值类型时。例如,如果你设计一个用来表现有理数的类,允许从整数到有理数的隐式转换:
class Rational {public:Rational(int numerator = 0, int denominator = 1);// 非explicit,允许int-to-Rational隐式转换int-to-Rationalint numerator() const; // 分子和分母的访问函数int denominator() const;private:...};应该支持算术运算,比如加法,乘法等等,但不能确定是通过成员函数、非成员函数、还是非成员的友元函数来实现它们。当你摇摆不定的时候,你应该坚持面向对象的原则。于是有理数的乘法与Rational类相关,所以在Rational类的内部实现有理数的operator*似乎更加正常。我们先让operator*成为Rational的一个成员函数:
class Rational {public:...const Rational operator*(const Rational& rhs) const; //operator*作为成员函数};Rational oneEighth(1, 8);Rational oneHalf(1, 2);Rational result = oneHalf * oneEighth; // fineresult = result * oneEighth; // fine
这个设计让你在有理数相乘时不费吹灰之力,但你还希望支持混合模式的操作,以便让 Rational能够和其它类型(如int)相乘。毕竟两个数相乘很正常,即使它们碰巧是不同类型的数值:
result = oneHalf * 2; // fineresult = 2 * oneHalf; // error
只有一半行得通,但乘法必须是可交换的。当以对应的函数形式重写上述两个式子,问题所在便一目了然:
result = oneHalf.operator*(2);result = 2.operator*(oneHalf);
对象oneHalf是一个包含 operator* 的类实例,所以编译器调用那个函数。然而整数2没有operator*成员函数。编译器同样要寻找可被如下调用的非成员operator*(也就是说,在 namespace 或全局范围内的operator*):
result = operator*(2, oneHalf);
但在本例中,没有非成员的接受int和Rational的operator*函数,所以搜索失败。再看那个成功的调用,它的第二个参数是整数2,而Rational::operator*却持有一个 Rational对象作为它的参数。这里发生了隐式类型转换。编译器知道你传递一个int而那个函数需要一个Rational,通过用你提供的int调用Rational的构造函数,它们能做出一个相配的Rational。换句话说,它们将那个调用或多或少看成如下这样:
const Rational temp(2); // 根据2建立一个临时Rational对象result = oneHalf * temp; // 等同于oneHalf.operator*(temp);当然,编译器这样做仅仅是因为提供了一个非explicit构造函数。如果Rational的构造函数是explicit,那两句语句都将无法编译,但至少语句的行为保持一致。
这两个语句一个可以编译而另一个不行的原因在于,当参数列在参数列表中的时候,才有资格进行隐式类型转换。现在支持混合运算的方法或许很清楚了:让operator*作为非成员函数,因此就允许将隐式类型转换应用于所有参数:
class Rational {... // 不包括operator*};const Rational operator*(const Rational& lhs, const Rational& rhs){return Rational(lhs.numerator() * rhs.numerator(),lhs.denominator()* rhs.denominator());}Rational oneFourth(1, 4);Rational result;result = oneFourth * 2; // fineresult = 2 * oneFourth; // it works!
另外,仅仅因为函数不应该作为成员并不自动意味着它应该作为友元。
关于operator*参考该文章条款21 必须返回对象时,别妄想返回其reference
0 0
- 条款24:若所有参数皆需类型转换,请为此采用non-member函数
- 条款24:若所有参数皆需类型转换,请为此采用non-member函数
- 条款24:若所有参数皆需类型转换,请为此采用non-member函数
- 条款24::若所有参数皆需类型转换,请为此采用 non-member 函数
- 条款24:若所有参数皆需类型转换,请为此采用non-member函数
- 条款24 若所有参数皆需类型转换,请为此采用non-member函数
- 条款24 若所有参数皆需类型转换,请为此采用non-member函数
- 《Effective C++》学习笔记条款24 若所有参数皆需类型转换,请为此采用non-member函数
- Effective C++:条款24:若所有参数皆需类型转换,请为此采用non-member函数
- 读书笔记《Effective C++》条款24:若所有参数皆需类型转换,请为此采用non-member函数
- 条款24:若所有参数都需要类型转换,请为此采用non-member函数
- 《Effect C++》学习------条款24 :若所有参数皆须类型转换,请为此采用non-member函数
- item24: 若所有参数皆需类型转换,请为此采用non-member函数
- Effective C++ 读书笔记 条款24:若所有参数皆需类型转换,则为此采用non-member 函数
- Effective C++ Item 24 若所有参数皆需类型转换,请为此采用non-member函数
- C++之若所有参数皆需类型转换,请为此采用non-member函数(24)---《Effective C++》
- effective c++ 若所有参数皆需要类型转换,请为此采用non-member函数
- 条款24:若所有参数皆需类型转化,请谓词函数采用non-member函数
- Asp.net核心对象
- AAPT使用小结
- 2206 IP的计算 HDU
- 正则表达式(Foundation自带)
- 什么是信息安全
- 条款24 若所有参数皆需类型转换,请为此采用non-member函数
- Markdown中编写LaTeX数学公式
- 常量指针和指向常量的指针
- JDBC之java使用oracle中scott表实现增删改查.1
- 1. linux 用户会话结束的实质
- Android---9---简单的计算器
- dos拼接字符串以及截取字符串
- KMP算法--转
- 正则表达式(开源框架)