C++箴言:类型转换时定义非成员函数
2011-09-08 01:02
519 查看
提要:《C++箴言:声明为非成员函数的时机》阐述了为什么只有non-memberfunctions(非成员
《C++箴言:声明为非成员函数的时机》阐述了为什么只有 non-member functions(非成员函数)适合于应用到所有 arguments(实参)的 implicit type conversions(隐式类型转换),而且它还作为一个示例使用了一个 Rational class 的 operator* function。我建议你在阅读本文之前先熟悉那个示例,因为本文进行了针对《C++箴言:声明为非成员函数的时机》中的示例做了一个无伤大雅(模板化 Rational 和 operator*)的扩展讨论:
就像在《C++箴言:声明为非成员函数的时机》中,我想要支持 mixed-mode arithmetic(混合模式运算),所以我们要让下面这些代码能够编译。我们指望它能,因为我们使用了和 Item 24 中可以工作的代码相同的代码。仅有的区别是 Rational 和 operator* 现在是 templates(模板):
编译失败的事实暗示对于模板化 Rational 来说,有某些东西和 non-template(非模板)版本不同,而且确实存在。在《C++箴言:声明为非成员函数的时机》中,编译器知道我们想要调用什么函数(取得两个 Rationals 的 operator*),但是在这里,编译器不知道我们想要调用哪个函数。作为替代,它们试图断定要从名为 operator* 的 template(模板)中实例化出(也就是创建)什么函数。它们知道它们假定实例化出的某个名为 operator* 的函数取得两个 Rational<T>
类型的参数,但是为了做这个实例化,它们必须断定 T 是什么。问题在于,它们做不到。
在推演 T 的尝试中,它们会察看被传入 operator* 的调用的 arguments(实参)的类型。在当前情况下,类型为 Rational<int>(oneHalf 的类型)和 int(2 的类型)。每一个参数被分别考察。
使用 oneHalf 的推演很简单。operator* 的第一个 parameter(形参)被声明为 Rational<T> 类型,而传入 operator* 的第一个 argument(实参)(oneHalf) 是 Rational<int> 类型,所以 T 一定是 int。不幸的是,对其它参数的推演没那么简单。operator* 的第二个 parameter(形参)被声明为 Rational<T> 类型,但是传入 operator* 的第二个 argument(实参)(2) 的 int 类型。在这种情况下,让编译器如何断定
T 是什么呢?你可能期望它们会使用 Rational<int> 的 non-eXPlicit constrUCtor(非显式构造函数)将 2 转换成一个 Rational<int>,这样就使它们推演出 T 是 int,但是它们不这样做。它们不这样做是因为在 template argument deduction(模板实参推演)过程中从不考虑 implicit type conversion functions(隐式类型转换函数)。从不。这样的转换可用于函数调用过程,这没错,但是在你可以调用一个函数之前,你必须知道哪个函数存在。为了知道这些,你必须为相关的
function templates(函数模板)推演出 parameter types(参数类型)(以便你可以实例化出合适的函数)。但是在 template argument deduction(模板实参推演)过程中不考虑经由 constructor(构造函数)调用的 implicit type conversion(隐式类型转换)。《C++箴言:声明为非成员函数的时机》不包括 templates(模板),所以 template argument deduction(模板实参推演)不是一个问题,现在我们在
C++ 的 template 部分,这是主要问题。
在一个 template class(模板类)中的一个 friend declaration(友元声明)可以指涉到一个特定的函数,我们可以利用这一事实为受到 template argument deduction(模板实参推演)挑战的编译器解围。这就意味着 class Rational<T> 可以为 Rational<T> 声明作为一个 friend function(友元函数)的 operator*。class templates(类模板)不依靠 template argument deduction(模板实参推演)(这个过程仅适用于
function templates(函数模板)),所以 T 在 class Rational<T> 被实例化时总是已知的。通过将适当的 operator* 声明为 Rational<T> class 的一个 friend(友元)使其变得容易
原帖地址:http://c.itwaka.com/basic1/39517.html
《C++箴言:声明为非成员函数的时机》阐述了为什么只有 non-member functions(非成员函数)适合于应用到所有 arguments(实参)的 implicit type conversions(隐式类型转换),而且它还作为一个示例使用了一个 Rational class 的 operator* function。我建议你在阅读本文之前先熟悉那个示例,因为本文进行了针对《C++箴言:声明为非成员函数的时机》中的示例做了一个无伤大雅(模板化 Rational 和 operator*)的扩展讨论:
template<typename T> class Rational { public: Rational(const T& numerator = 0, // see《C++箴言:用传引用给const取代传值》for why params const T& denominator = 1); // are now passed by reference const T numerator() const; // see《C++箴言:避免返回对象内部构件的句柄》for why return const T denominator() const; // values are still passed by value, ... // Item 3 for why they're const }; template<typename T> const Rational<T> operator*(const Rational<T>& lhs, const Rational<T>& rhs) { ... } |
Rational<int> oneHalf(1, 2); // this example is from 《C++箴言:声明为非成员函数的时机》, // except Rational is now a template Rational<int> result = oneHalf * 2; // error! won't compile |
类型的参数,但是为了做这个实例化,它们必须断定 T 是什么。问题在于,它们做不到。
在推演 T 的尝试中,它们会察看被传入 operator* 的调用的 arguments(实参)的类型。在当前情况下,类型为 Rational<int>(oneHalf 的类型)和 int(2 的类型)。每一个参数被分别考察。
使用 oneHalf 的推演很简单。operator* 的第一个 parameter(形参)被声明为 Rational<T> 类型,而传入 operator* 的第一个 argument(实参)(oneHalf) 是 Rational<int> 类型,所以 T 一定是 int。不幸的是,对其它参数的推演没那么简单。operator* 的第二个 parameter(形参)被声明为 Rational<T> 类型,但是传入 operator* 的第二个 argument(实参)(2) 的 int 类型。在这种情况下,让编译器如何断定
T 是什么呢?你可能期望它们会使用 Rational<int> 的 non-eXPlicit constrUCtor(非显式构造函数)将 2 转换成一个 Rational<int>,这样就使它们推演出 T 是 int,但是它们不这样做。它们不这样做是因为在 template argument deduction(模板实参推演)过程中从不考虑 implicit type conversion functions(隐式类型转换函数)。从不。这样的转换可用于函数调用过程,这没错,但是在你可以调用一个函数之前,你必须知道哪个函数存在。为了知道这些,你必须为相关的
function templates(函数模板)推演出 parameter types(参数类型)(以便你可以实例化出合适的函数)。但是在 template argument deduction(模板实参推演)过程中不考虑经由 constructor(构造函数)调用的 implicit type conversion(隐式类型转换)。《C++箴言:声明为非成员函数的时机》不包括 templates(模板),所以 template argument deduction(模板实参推演)不是一个问题,现在我们在
C++ 的 template 部分,这是主要问题。
在一个 template class(模板类)中的一个 friend declaration(友元声明)可以指涉到一个特定的函数,我们可以利用这一事实为受到 template argument deduction(模板实参推演)挑战的编译器解围。这就意味着 class Rational<T> 可以为 Rational<T> 声明作为一个 friend function(友元函数)的 operator*。class templates(类模板)不依靠 template argument deduction(模板实参推演)(这个过程仅适用于
function templates(函数模板)),所以 T 在 class Rational<T> 被实例化时总是已知的。通过将适当的 operator* 声明为 Rational<T> class 的一个 friend(友元)使其变得容易
原帖地址:http://c.itwaka.com/basic1/39517.html
相关文章推荐
- C++箴言:类型转换时定义非成员函数
- C++ 若所有参数皆需类型转换,请为此采用非成员(non-member)函数
- C++箴言:类型转换时定义非成员函数
- C++ Pirmer : 第十五章 : 面向对象程序设计之基类和派生的定义、类型转换与继承与虚函数
- C++ Pirmer : 第十四章 : 重载运算符与类型转换之函数调用运算符与标准库的定义的函数对象
- 条款46:需要类型转换时请为模板定义非成员函数
- 读书笔记 effective c++ Item 24 如果函数的所有参数都需要类型转换,将其声明成非成员函数
- c++中的类型转换函数定义
- c++ 将string类型转换成int、 long、 double类型函数
- C++强制转换不同声明或类型的函数指针隐患
- C++箴言:用成员函数模板接受兼容类型
- C++中 当函数所有参数都需要类型转换时 需要将其声明为non-member函数
- C++ 关于static_cast reinterpret_cast dynamic_cast 以及 const_cast 用于类型转换的函数使用 20180315 day7
- C++箴言:用成员函数模板接受兼容类型
- 【c++系列】类型转换以及预处理器定义的常量(当前的文件名、行号、时间、日期)
- C++ - 使用非成员函数(non-member)处理函数的所有参数都需要类型转换
- 隐式类型转换与非成员函数(effective C++ 条款24&46)
- C++函数不定参数函数和类型强制转换
- 为什么在C++使用pthread_create()的时候,类成员函数做线程的处理函数必须要定义成static类型的?
- 如何用python的装饰器定义一个像C++一样的强类型函数