C++ 需要类型转换时请为模板定义非成员函数

原创 2018年04月16日 19:13:52

20180403 C++ 需要类型转换时请为模板定义非成员函数


只有非成员函数才有能力“在所有实参身上实施隐式类型转换”,该条款可以通过Rational(有理数)类和operator*函数为例证明。本文将扩充这一条款:将Rational类和operator*函数模板化:


template<typename T>
class Rational
{
public:
  Rational(const T& numerator = 0,
           const t& denominator = 1);
  const T numerator() const;
  const T denominator() const;
  ...
};


template<typename T>
const Rational<T> operator*(const Rational<T>& lhs,
                            const Rational<T>& rhs)
{...}


我们希望支持混合式算数运算,即:
Rational<int> oneHalf(1,2);


Rational<int> result = oneHalf * 2;//错误,无法通过编译。


上述失败给我们的启示是,模板化的Rational里的某些东西似乎和他的非模板版本不同,在这里编译器不知道我们想要调用哪个函数。取而代之的是它们试图想出什么函数被命名为operator*的模板具现化(产生)出来。它们知道它们可以具现化某个“名为operator*并接受两个Rational<T>参数”的函数。但为完成这一具现化行为,必须先算出T是什么,问题的它没有这个能耐。








只要利用一个事实,我们就可以缓和编译器在模板参数推导方面受到的挑战:模板类里的友元声明式可以指涉某个特定函数。那意味着类 Rational<T>可以声明operator*是它的一个友元函数。类模板并不依赖模板实参推导(后者只施行于函数模板身上),所以编译器总是能够在类Rational<T>具现化时得知T,因此令Rational<T>类声明适当的operator*为其友元函数,可简化整个问题:






template<typename T>
class Rational
{
public:
  ...
  friend
  const Rational operator*(const Rational<T>& lhs,//声明operator*函数
                           const Rational<T>& rhs);
};


template<typename T>
const Rational<T> operator*(const Rational<T>& lhs,//定义operator*函数
                            const Rational<T>& rhs)
{...}


现在对operator*的混合调用可以通过编译了,






我们可以将operator*函数本体合并至其声明式中:


template<typename T>
class Rational
{
pubblic:
  ...
  friend const Rational operator*(const Rational& lhs,
                                  const Rational& rhs)
  {
    return Rational(lhs.numerator() * rhs.numerator(),
                    lhs.denominator() * rhs.denominator());
  }
}


这项技术的特点是,我们虽然使用友元,却与友元的传统用途“访问类的非公有成分”毫不相干。为了让转型可能发生于所有实参身上,我们需要一个非成员函数;为了让类型转换可能发生于所有实参身上,我们需要一个非成员函数;为了让这个函数被自动具现化,我们需要将他声明在类内部,而在类里声明非成员函数的唯一办法就是:令他成为一个友元,因此我们就这样做了。










注意:
当我们编写一个类模板时,而他所提供的“与此模板相关的”函数支持“所有参数的隐式类型转换”的时候,请将那些函数定义为“类模板内部的友元函数”。


























































































Effective C++ 46条 需要类型转换时请为模板定义非成员函数

背景:承接条款24条(请先去了解),那么,之于template实现版本呢? template class Rational { public: Rational(const T& numer...
  • xujiali5172923
  • xujiali5172923
  • 2015-06-05 15:01:11
  • 350

Item 46:需要类型转换时,应当在类模板中定义非成员函数

Item 46: Define non-member functions inside templates when type conversions are desired. Item 2...
  • yangjvn
  • yangjvn
  • 2016-02-19 11:52:59
  • 975

将重载运算符定义为成员函数还是普通的非成员函数

● 赋值 = 、下标[ ]、调用( )、和成员访问箭头 ->必须是成员函数 ● 符合符合赋值运算符应该是成员,但是并非必须 ● 改变对象状态的运算符或者与给定类型密切相关的运算符,如 递增...
  • wy11933
  • wy11933
  • 2016-10-25 12:17:02
  • 1171

C++基础知识复习--运算符重载(非成员函数重载和成员函数重载)

//+, -, >, 运算符的重载 #include using namespace std; class Complex { private: float Vector_x; f...
  • Bugggget
  • Bugggget
  • 2017-03-09 14:33:37
  • 1642

effective C++之需要类型转换时,为模板定义非成员函数

  • gettogetto
  • gettogetto
  • 2016-11-06 15:40:42
  • 139

重载的操作符成员函数与非成员函数

今天看effective STL第26条条款时,发现自己之前没意识到如下的几点(看来自己的c++基础还是渣渣水平o(╯□╰)o)。 如果一个类重载操作符,当在全局域内也重载了同样的操作符,那么在调用该...
  • AQ14AQ1
  • AQ14AQ1
  • 2015-11-03 22:37:36
  • 1718

C++ - 模板函数需要类型转换时使用友元(friend)模板函数

模板函数需要类型转换时使用友元(friend)模板函数 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24357301 非...
  • u012515223
  • u012515223
  • 2014-04-23 12:30:31
  • 2605

C++ 12.1 类的定义、声明、成员函数、数据成员

简介 数据成员一般声明为private,以实现信息的隐蔽 成员函数一般声明为public,以提供外界使用的接口 构造函数一般声明为public,以便创建类的对象 创建一个类类型的对象时,编译器会自动使...
  • hlsdbd1990
  • hlsdbd1990
  • 2015-06-17 14:42:39
  • 1227

类模板、函数模板以及类成员函数在类外定义情况

1函数模板的写法 函数模板的一般形式如下: Template 返回类型 函数名(形参表) {//函数定义体 } 说明: template是一个声明模板的关键字,表示声明一个...
  • wonengguwozai
  • wonengguwozai
  • 2016-08-03 21:09:49
  • 3846
收藏助手
不良信息举报
您举报文章:C++ 需要类型转换时请为模板定义非成员函数
举报原因:
原因补充:

(最多只允许输入30个字)