C++中隐式类型转换学习笔记

1 operator隐式类型转换

1.1 std::ref源码中reference_wrapper隐式类型转换

在std::ref的实现中有如下一段代码:

template<typename _Tp>
 class reference_wrapper
 : public _Reference_wrapper_base<typename remove_cv<_Tp>::type>
 {
  _Tp* _M_data;

 public:
  typedef _Tp type;

  reference_wrapper(_Tp& __indata) noexcept
  : _M_data(std::__addressof(__indata))
  { }

  reference_wrapper(_Tp&&) = delete;

  reference_wrapper(const reference_wrapper&) = default;

  reference_wrapper&
  operator=(const reference_wrapper&) = default;
  //operator的隐式类型转换
  operator _Tp&() const noexcept
  { return this->get(); }

  _Tp&
  get() const noexcept
  { return *_M_data; }

  template<typename... _Args>
 typename result_of<_Tp&(_Args&&...)>::type
 operator()(_Args&&... __args) const
 {
  return __invoke(get(), std::forward<_Args>(__args)...);
 }
 };

注意看operator操作符重载:

operator _Tp&() const noexcept
  { return this->get(); }

就是用于类型转换。

1.2 简单的例子-实现一个class转为int的示例

#include <iostream>
/*
 *
 * c++ operator的隐式类型转换
 * 参见std::ref的实现
 */
void f(int a)
{
 std::cout << "a = " << a << std::endl;
}
class A{
 public:
 A(int a):num(a){}
 ~A() {}

 operator int()
 {
  return num;
 }
 int num;
};

int main()
{
 A a(1);
 std::cout << a + 1 << std::endl;
 f(a);
 return 0;
}

当然除了通过operator实现隐式类型转换,c++中还可以通过构造函数实现。

2 构造函数实现隐式类型转换

在c++ primer一书中提到

可以用单个实参来调用的构造函数定义了从形参类型到该类类型的一个转换

看如下示例:

#include <iostream>
/*
 *
 * c++ 构造的隐式类型转换
 * 参见std::ref的实现
 */
class B{
 public:
 B(int a):num(a){}
 ~B() {}

 int num;
};

class A{
 public:
 A(int a):num(a){}
 A(B b):num(b.num){}
 ~A() {}

 int fun(A a)
 {
  std::cout << num + a.num << std::endl;
 }

 int num;
};

int main()
{
 B b(1);
 A a(2);
 //通过构造函数实现了隐式类型转换
 a.fun(b); //输出结果为3
 return 0;
}

特别需要注意的是单个实参,构造函数才会有隐式转换,一个条件不满足都是不行。

3 使用explicit关键字避免构造函数隐式转换

有些时候我们并不希望发生隐式转换,不期望的隐式转换可能出现意外的结果,explicit关键词可以禁止之类隐式转换,将上述class A的构造函数改为如下

class A{
 public:
 A(int a):num(a){}
 explicit A(B b):num(b.num){}
 ~A() {}

 int fun(A a)
 {
  std::cout << num + a.num << std::endl;
 }

 int num;
};

再次运行程序出现提示:

op2.cpp: In function ‘int main()':
op2.cpp:29:12: error: no matching function for call to ‘A::fun(B&)'
a.fun(b);
^
op2.cpp:16:9: note: candidate: int A::fun(A)
int fun(A a)
^~~
op2.cpp:16:9: note: no known conversion for argument 1 from ‘B' to ‘A'

这个时候调用方式修改更改为:

int main()
{
 B b(1);
 A a(2);
 a.fun(A(b));
 return 0;
}

只能感叹C++语言的博大精深,这篇文章还只是对隐式转换的入门级总结。

参考:

《C++ Primer》隐式类类型转换学习整理

以上就是C++中隐式类型转换学习笔记的详细内容,更多关于C++中隐式类型转换的资料请关注我们其它相关文章!

(0)

相关推荐

  • 《C++ Primer》隐式类类型转换学习整理

    C++ Primer中有这样一句话:可以用单个实参来调用的构造函数定义了从形参类型到该类类型的一个转换.这句话用下面一段代码表示为: class A { A(B b);//单个实参的构造函数 func(A a); } ..... A a: B b; a.func(b);//func函数本应该接受A类型的实参,但是由于特殊构造函数的存在,所以B类型的参数b借助这个特殊的构造函数转化为A类型对象,完成转换.所以这条语句是正确的 从上述代码段可以看出来,单个实参调用的构造函数定义了类类型到其他类型的转

  • c++隐式类型转换示例分享

    复制代码 代码如下: /*=============================================================================#     FileName: explicit_try.cc#         Desc: 验证含有一个参数的非explicit构造函数是否可以拷贝初始化=============================================================================*/#in

  • C++中隐式类型转换学习笔记

    1 operator隐式类型转换 1.1 std::ref源码中reference_wrapper隐式类型转换 在std::ref的实现中有如下一段代码: template<typename _Tp> class reference_wrapper : public _Reference_wrapper_base<typename remove_cv<_Tp>::type> { _Tp* _M_data; public: typedef _Tp type; refere

  • 总结Javascript中的隐式类型转换

    JavaScript的数据类型分为六种,分别为null,undefined,boolean,string,number,object.object是引用类型,其它的五种是基本类型或者是原始类型. 比如像是Number() ,还是parseInt() .parseFloat()都属于显示类型转换(强制类型转换): 这一节我们来看一下隐式类型转换(自动转换). 数值自动转换为字符串 var a = 123; alert(a+'456'); // 输出 123456 "+"号为连接符 字符串

  • Python学习笔记之列表推导式实例分析

    本文实例讲述了Python学习笔记之列表推导式.分享给大家供大家参考,具体如下: 列表推导式 列表推导式可以快速简练地创建列表 之前的复杂写法: capitalized_cities = [] for city in cities: capitalized_cities.append(city.title()) 简化后的写法: capitalized_cities = [city.title() for city in cities] 由此可见:借助列表推导式,我们可以使用 for 循环用一步创

  • ES6学习笔记之Set和Map数据结构详解

    本文实例讲述了ES6学习笔记之Set和Map数据结构.分享给大家供大家参考,具体如下: 一.Set ES6提供了新的数据结构Set.类似于数组,只不过其成员值都是唯一的,没有重复的值. Set本身是一个构造函数,用来生成Set数据结构. 1 . Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化. var s = new Set(); var set = new Set([1, 2, 3, 4, 4]); [...set] // [1, 2, 3, 4] var items =

  • C#学习笔记整理_变量等基础语法(必看篇)

    C#学习笔记1: 变量的作用域冲突时,调用实例变量:this.a,调用类变量:类名.a 常量总是静态的,必须初始化,一般用全大写格式,声明关键字为const,如const int NUNBE = 10; C#的基本预定义类型内置于.NET Framework结构中(System),object是基类: 整型:System.SByte.System.Int16.System.Int32.System.Int64 有符号的8位.16位.32位.64位分别表示为sbyte.short.int.long

  • Python学习笔记基本数据结构之序列类型list tuple range用法分析

    本文实例讲述了Python学习笔记基本数据结构之序列类型list tuple range用法.分享给大家供大家参考,具体如下: list 和 tuple list:列表,由 [] 标识: 有序:可改变列表元素 tuple:元组,由 () 标识: 有序:不可改变元组元素(和list的主要区别) list 和 tuple 的创建: print([]) # 空list print(["a",1,True]) # 元素类型不限 print([x for x in range(0,6)]) #

  • Python树莓派学习笔记之UDP传输视频帧操作详解

    本文实例讲述了Python树莓派学习笔记之UDP传输视频帧操作.分享给大家供大家参考,具体如下: 因为我在自己笔记本电脑上没能成功安装OpenCV-Contrib模块,因此不能使用人脸识别等高级功能,不过已经在树莓派上安装成功了,所以我想实现把树莓派上采集的视频帧传输到PC的功能,这样可以省去给树莓派配显示屏的麻烦,而且以后可能可以用在远程监控上. 1 UDP还是TCP 首先考虑用哪种传输方式,平常TCP用的非常多,但是像视频帧这种数据用TCP不是太合适,因为视频数据的传输最先要考虑的是速度而不

  • C++ Primer Plus 第四章之C++ Primer Plus复合类型学习笔记

    目录 1. 数组概述 1.1 数组的定义 1.2 数组的声明 1.3 复合类型的数组 1.4 数组的初始化规则 1.5 C++11数组初始化方法 2. 字符串 2.1 C++处理字符串的两种方式: 2.2 字符串常量的拼接 2.4 读取一行字符串的输入 3. string类 3.1 string对象的方式 3.2 复制.拼接和附加 4. 结构简介 4.1 创建结构的步骤: 4.2 结构的定义: 4.3 结构的初始化(C++11) 4.4 成员赋值 5. 共用体 5.1 结构体和共用体的区别 5.

  • AngularJS学习笔记之表单验证功能实例详解

    本文实例讲述了AngularJS学习笔记之表单验证功能.分享给大家供大家参考,具体如下: 一.执行基本的表单验证 <!DOCTYPE html> <html ng-app='exampleApp'> <head> <meta charset="UTF-8"> <title>表单</title> <script src="../../js/angular.min.js" type="

随机推荐