41-42 - 类型转换函数

---- 整理自狄泰软件唐佐林老师课程

1. 再论类型转换

  • 标准数据类型之间会进行 隐式的 类型安全转换
  • 转换规则如下:
    在这里插入图片描述

1.1 实例分析

#include <iostream>
#include <string>

using namespace std;

int main()
{   
    short s = 'a';
	char c = 'c';
    int i = -2000;
    unsigned int ui = 1000;
    double d = i;
    
    cout << "d = " << d << endl;
    cout << "ui = " << ui << endl;
    cout << "ui + i = " << ui + i << endl; // uint + int --> uint + uint
    
    if( (ui + i) > 0 )
    {
        cout << "Positive" << endl;
    }
    else
    {
        cout << "Negative" << endl;
    }
    
    cout << "sizeof(s + c) = " << sizeof(s + c) << endl; // short + char --> int + int 编译器为了高效 char --> int, short --> int
    
    return 0;
}

在这里插入图片描述

1.2 问题

  • 普通类型与类类型之间能否进行类型转换?
  • 类类型之间能否进行类型转换?

2. 问题一:普通类型 & 类类型

2.1 编程实验:普通类型 & 类类型

#include <iostream>
#include <string>

using namespace std;

class Test
{
	int mi;
public:
	Test() {}
	Test(int i) {
		mi = i;
	}
	int value() {
		return mi;
	}
};

int main()
{   
    Test t;
	cout << "t.mi = " << t.value() << endl;

	t = 5; // 转换构造函数
		   // 5 默认为 int,通过转换构造函数 Test(int i) 进行转换
		   // --> t = Test(5);
	cout << "t.mi = " << t.value() << endl;
    
    return 0;
}

在这里插入图片描述

2.2 再论构造函数

  • 构造函数可以定义不同类型的参数
  • 参数满足下列条件时称为 转换构造函数
    • 有且仅有一个参数
    • 参数是 基本类型
    • 参数是 其它类类型

2.3 旧式的 C 方式强制类型转换

在这里插入图片描述

2.4 编译器的行为

  • 编译器会尽力尝试让源码通过编译
Test t;
t = 100;

在这里插入图片描述

  • 编译器尽力尝试的结果是 隐式类型转换
#include <iostream>
#include <string>

using namespace std;

class Test
{
	int mValue;
public:
	Test() {}
	Test(int i) {
		mValue = i;
	}
	Test operator+(const Test& t) {
		Test ret(mValue + t.mValue);
		return ret;
	}
	int value() {
		return mValue;
	}
};

int main()
{   
    Test t;
	t = 5; // 转换构造函数
		   // 5 默认为 int,通过转换构造函数 Test(int i) 进行转换
		   // --> t = Test(5);
	
	Test r;
	
	r = t + 10; // 隐式转换 Test + int --> Test + Test(10)
				// 可能引入 bug,可能是手误,本意并不是如此,但是编译不报错
	
	cout << "r.mValue = " << r.value() << endl;

    return 0;
}

在这里插入图片描述

  • 隐式类型转换
    • 会让程序以意想不到的方式进行工作
    • 是工程中 bug 的重要来源
    • 工程中通过 explicit 关键字 杜绝编译器的转换尝试
    • 转换构造函数explicit 修饰时只能进行 显示转换
#include <iostream>
#include <string>

using namespace std;

class Test
{
	int mValue;
public:
	Test() {
		mValue = 0;
	}
	explicit Test(int i) { // 必须显示转换
		mValue = i;
	}
	Test operator+(const Test& t) {
		Test ret(mValue + t.mValue);
		return ret;
	}
	int value() {
		return mValue;
	}
};

int main()
{   
    Test t;
	t = 5;
	
	Test r;
	
	r = t + 10; 
	
	cout << "r.mValue = " << r.value() << endl;

    return 0;
}

在这里插入图片描述

#include <iostream>
#include <string>

using namespace std;

class Test
{
	int mValue;
public:
	Test() {
		mValue = 0;
	}
	explicit Test(int i) { // 必须显示转换
		mValue = i;
	}
	Test operator+(const Test& t) {
		Test ret(mValue + t.mValue);
		return ret;
	}
	int value() {
		return mValue;
	}
};

int main()
{   
    Test t;
	t = static_cast<Test>(5); // --> t = Test(5)
	
	Test r;
	
	r = t + static_cast<Test>(10); // --> r = t + Test(10)
	
	cout << "r.mValue = " << r.value() << endl;

    return 0;
}

在这里插入图片描述

  • 转换方式:
static_cast<ClassName>(value);
ClassName(value);
(ClassName)value;  // 不推荐

3. 问题二:类类型

  • 类类型是否能够类型转换到普通类型?
  • - NO
#include <iostream>
#include <string>

using namespace std;

class Test
{

};

int main()
{   
    Test t;
	
	int i = t;

    return 0;
}

在这里插入图片描述

3.1 类型转换函数

  • C++ 类中可以定义 类型转换函数
  • 类型转换函数 用于将 类对象 转换为 其它类型
  • 语法规则:
    在这里插入图片描述

3.2 编程实验:类型转换函数初探

#include <iostream>
#include <string>

using namespace std;

class Test
{
	int mValue;
public:
	Test(int i = 0) {
		mValue = i;
	}
	int value() {
		return mValue;
	}
	operator int() { // 类型转换函数
		return mValue;
	}
};

int main()
{   
    Test t(100);
	int i = t;
	
	cout << "t.mValue = " << t.value() << endl;
	cout << "i = " << i << endl;

    return 0;
}

在这里插入图片描述

#include <iostream>
#include <string>

using namespace std;

class Test
{
	int mValue;
public:
	Test(int i = 0) {
		mValue = i;
	}
	int value() {
		return mValue;
	}
	operator int() { // 类型转换函数
		return mValue;
	}
};

int main()
{   
    Test t(100);
	// int i = t; 其实等价于
	int i = t.operator int();
	
	cout << "t.mValue = " << t.value() << endl;
	cout << "i = " << i << endl;

    return 0;
}

在这里插入图片描述

3.3 类型转换函数

  • 与转换构造函数具有同等的地位
  • 使得编译器 有能力将 对象 转化为 其它类型
  • 编译器能够 隐式的使用类型转换函数

3.4 编译器的行为

  • 编译器会尽力尝试让源码通过编译
Test t(1);
int i = t;

在这里插入图片描述

3.5 编程实验:类类型之间的转换

  • 类类型之间的相互转换
    • 类型转换函数 VS 转换构造函数
#include <iostream>
#include <string>

using namespace std;

class Test;

class Value
{
public:
    Value()
    {
    }
    explicit Value(Test& t)
    {
    }
};

class Test
{
    int mValue;
public:
    Test(int i = 0)
    {
        mValue = i;
    }
    int value()
    {
        return mValue;
    }
    operator Value()
    {
        Value ret;
        cout << "operator Value()" << endl;
        return ret;
    }
};

int main()
{   
    Test t(100);
    Value v = t;
    
    return 0;
}

3.5.1 通过类型转换函数

#include <iostream>
#include <string>

using namespace std;

class Demo
{
public:
	Demo() {}
};

class Test
{
	int mValue;
public:
	Test(int i = 0) {
		mValue = i;
	}
	int value() {
		return mValue;
	}
	operator Demo() { // 类型转换函数
		Demo ret;
		cout << "operator Demo()" << endl;
		return ret;
	}
};

int main()
{   
    Test t(100);
	Demo v = t; // 等价于 Demo v = t.operator Demo();

    return 0;
}

在这里插入图片描述

3.5.2 通过转换构造函数

#include <iostream>
#include <string>

using namespace std;

class Test; // Demo 中先使用了 Test 类型,需要先声明

class Demo
{
public:
	Demo() {
		
	}
	Demo(Test& t) { // 转换构造函数
		
	} 
};

class Test
{
	int mValue;
public:
	Test(int i = 0) {
		mValue = i;
	}
	int value() {
		return mValue;
	}
	/* 
	operator Demo() { // 类型转换函数
		Demo ret;
		cout << "operator Demo()" << endl;
		return ret;
	}
	*/
};

int main()
{   
    Test t(100);
	Demo v = t; // 等价于 Demo v = Demo(t);

    return 0;
}

在这里插入图片描述

3.5.3 类型转换函数可能与转换构造函数冲突

#include <iostream>
#include <string>

using namespace std;

class Test; // Demo 中先使用了 Test 类型,需要先声明

class Demo
{
public:
	Demo() {
		
	}
	Demo(Test& t) { // 转换构造函数
		
	} 
};

class Test
{
	int mValue;
public:
	Test(int i = 0) {
		mValue = i;
	}
	int value() {
		return mValue;
	}
	operator Demo() { // 类型转换函数
		Demo ret;
		cout << "operator Demo()" << endl;
		return ret;
	}
};

int main()
{   
    Test t(100);
	Demo v = t;
	
    return 0;
}

在这里插入图片描述

3.6 注意

  • 无法抑制隐式的类型转换函数调用
  • 类型转换函数可能与转换构造函数冲突
  • 工程中以 Type toType() 的公有成员代替类型转换函数
#include <iostream>
#include <string>

using namespace std;

class Test; // Demo 中先使用了 Test 类型,需要先声明

class Demo
{
public:
	Demo() {
		
	}
	explicit Demo(Test& t) { // 转换构造函数,explicit 必须显示转换
		
	} 
};

class Test
{
	int mValue;
public:
	Test(int i = 0) {
		mValue = i;
	}
	int value() {
		return mValue;
	}
	Demo toDemo() {
		Demo ret;
		cout << "Demo toDemo()" << endl;
		return ret;
	}
};

int main()
{   
    Test t(100);
	Demo v = t.toDemo();
	
    return 0;
}

在这里插入图片描述

4. 小结

  • C++ 类中可以定义类型转换函数
  • 类型转换函数用于将类对象转换为其它类型
  • 类型转换函数与转换构造函数具有同等的地位
  • 工程中以Type toType() 的公有成员代替了类型转换函数
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

uuxiang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值