10~C++ 类型转换函数(单参构造函数)

C++ 类型转换包括:隐式类型转换,显示类型转换
一、常用类型转换函数
1、引入 基本类型类型转换
代码中展示基本类型的隐式类型转换和显式类型转换

#include <iostream>
using namespace std;
int main(void) {
/*隐式转换允许规则*/
long count; //
count = 8; //int -> long int
double time; 
time  = 11; //int -> double
int side; // double -> int
side = 3.33; // double -> int
/*隐式转换规则不允许*/
//int *p = 10;

/*显示类型转换*/
count = (long) 8;
time = (double) 11;
side = (int)3.3;
int *p = (int*)10;
return 0;
}

2、C++类 类型转换函数
类型转换有几种情况
case 1
“=”两侧类型不一致,编译器选择将右侧类型转换为左侧类型,然后拷贝给左侧变量
case 2
函数调用时:函数声明的形参类型 与实参类型不一致
case 3
函数返回类型形参和实参类型不一致

case1

#include <iostream>
using namespace std;

struct Stack {
	Stack(void) {
		cout <<  "constructor" << endl;
	}
	Stack(int a ) {
		cout <<  "int convertor" << endl;
	}
	Stack(double b) {
		cout << "double convertor" << endl;
	}
	Stack(Stack const& that) {
		cout << "cp constructor" << endl;
	}
	Stack& operator= (Stack const& that) {
		cout <<"operator = " <<endl;
	}
};

int main(void) {
Stack s1;

/*case1 隐式类型转换*/
//先匿名构造一个Stack对象,然后使用赋值运算符=函数: 这就是隐式类型转换的本质
s1 = 2;
s1 = 3.3;

/*case1 显示类型转换,语法形式同隐式转换有区别,但过程是一样的*/
//新编译器语法
s1 = Stack(2);
s1 = Stack(3.3);
//旧编译器语法
s1 = (Stack)2;
s1 = (Stack)3.3;
return 0;
}

case2

#include <iostream>
using namespace std;

struct Stack {
	Stack(void) {
		cout <<  "constructor" << endl;
	}
	Stack(int a ) {
		cout <<  "int convertor" << endl;
	}
	Stack(double b) {
		cout << "double convertor" << endl;
	}
	Stack(Stack const& that) {
		cout << "cp constructor" << endl;
	}
	Stack& operator= (Stack const& that) {
		cout <<"operator = " <<endl;
	}
};
void input(Stack item) {
}
int main(void) {
Stack s1;
/*case2 隐式转换*/
input(10);
input(3.3);
/*case2 显示转换*/
input((Stack)10);
input((Stack)3.3);
return 0;
}

case3

#include <iostream>
using namespace std;

struct Stack {
	Stack(void) {
		cout <<  "constructor" << endl;
	}
	Stack(int a ) {
		cout <<  "int convertor" << endl;
	}
	Stack(double b) {
		cout << "double convertor" << endl;
	}
	Stack(Stack const& that) {
		cout << "cp constructor" << endl;
	}
	Stack& operator= (Stack const& that) {
		cout <<"operator = " <<endl;
	}
};
Stack output_int(void) {
	return 10;
	//return Stack(10);
}
Stack output_double (void) {
	//return 3.3;
	return Stack(3.3);
}

int main(void) {
Stack s1;
/*case3 隐式转换*/
output_int();
/*case3 显示转换*/
output_double();
return 0;
}

3、 以上基本列举了显示转换和隐式转换的情景,本节记录 禁止隐式类型转换的方法
使用explicit 关键字 声明类型转换函数,将禁止隐式类型转换语法通过编译(explicit 只用于类声明内,其次只能用来修饰构造函数(无参或者多参>1)或者是类型转换函数(又名类型转换函数))

#include <iostream>
using namespace std;

struct Stack {
	explicit Stack(void) {
		cout <<  "constructor" << endl;
	}
	explicit Stack(int a ) {
		cout <<  "int convertor" << endl;
	}
	explicit Stack(double b) {
		cout << "double convertor" << endl;
	}
	//拷贝构造函数 原则上是没必要使用explicit 声明的
	Stack(Stack& that) {
		cout << "None const cp constructor" << endl;
	}
	Stack(Stack const& that) {
		cout << "cp constructor" << endl;
	}
	Stack& operator= (Stack const& that) {
		cout <<"operator = " <<endl;
	}
};
void input(Stack item) {
}
Stack output_int(void) {
	return Stack(10);
	//return Stack(10);
}
Stack output_double (void) {
	//return 3.3;
	return Stack(3.3);
}

int main(void) {
Stack s1;
Stack s2;

/*int -> Stack 类型隐式转换 被禁止,编译器尝试调用 operator=(int) 这个接口*/
//s1  = 1;

/*显示类型转换 int-> Stack , 然后调用operator= (Stack const& that)函数*/
s1 = Stack(1);

/*形参为对象,首先检查构造函数语法,拷贝构造匿名对象 Stack(Stack&)*/
input(s1);

/*input(Stack(10)) input函数原型为void input(Stack item);Stack(10)返回一个Stack对象;编译器首先考虑调用input(Stack(Stack(10)))是否存在匹配,即考虑调用Stack(Stack const&),不存在匹配则报错。 后来发现类型转换函数,这个接口更佳,于是选择类型转换函数*/
input(Stack(10));

/*返回语句return 同函数调用存在同样的规则 return Stack(10), 首先编译器构造匿名对象,考虑Stack(Stack const& that),声明不存在报错。 后面发现类型转换构造更佳*/
output_int();
/*case3 显示转换*/
output_double();
return 0;
}

4、对象构造 与 类型转换
Classname T = type b;

#include <iostream>
using namespace std;
struct Stack {
	explicit Stack(void) {
		cout <<  "constructor" << endl;
	}
	explicit Stack(int a ) {
		cout <<  "int convertor" << endl;
	}
	explicit Stack(double b) {
		cout << "double convertor" << endl;
	}
	//拷贝构造函数 原则上是没必要使用explicit 声明的
	Stack(Stack& that) {
		cout << "None const cp constructor" << endl;
	}
	Stack(Stack const& that) {
		cout << "cp constructor" << endl;
	}
	Stack& operator= (Stack const& that) {
		cout <<"operator = " <<endl;
	}
	Stack& operator= (int rhs) {
		cout << "operator=(int)" << endl;
	}
};
int main() {

/*构造的形式:语法类型为构造Stack s1, 匹配原型为 Stack const&)类型,因此没有这个原型的声明,将导致编译失败
接下来,编译器发现类型转换函数更佳,因此本调用最终使用了 Stakc(int)*/
Stack s1  = Stack(10); //int convertor

/*不是构造的形式:首先考虑operator=,然后检查类型转换函数Stack(int)*/
s1 = Stack(10); //int convertor , operator=

/*不是构造的形式:首先考虑operator=(int),存在则调用*/
s1 = 10;
return 0;
}

二、其他类型转换函数
1、将类类型转换为基本类型

#include <iostream>
using namespace std;
struct Stack {
	operator int() {
		return 10;
	}
	explicit operator double() {
		return 9.9;
	}
	explicit Stack(void) {
	}
};
int main() {
Stack s1;
int i = s1;
double d = (double) s1;
return 0;
}

2、多操作数运算 类型转换

#include <iostream>
using namespace std;
struct Stack {
	Stack operator+(Stack const& that) const{
		cout <<"operator+ with rhs that" << endl;
		return *this;
	}
	friend Stack operator-(Stack const& lfs, Stack const& rhs); 
	Stack (double rhs) {
		cout <<"double convertor" << endl;
	}
	explicit Stack(void) {
	}
};

Stack operator- (Stack const& lfs, Stack const& rhs){
	cout << "operator- with rhs that" <<endl;
	return lfs;
}
 
int main() {
Stack s1;
Stack s2;
Stack s3 = s2 + s1; //s2.operator+(s1) -> copy constructor
Stack s4 = s2 - s1;//operator-(s2,s1) -> copy constructor


s3  = s2 + s1; //operator+s2.(s1) ->  operator=
s4 = s2 -s1; //operator-(s2,s1) -> operator=

//s2.operator+(Stack(3.3));
s3 = s2 + 3.3;
/*以下语法不成立*/
//s3 = 3.3 + s2;

//s4 = operator-(s2,Stack(3.3))
s4 = s2 - 3.3;
//s4 = operator-(Stack(3.3),s2)
s4 = 3.3 -s2;

return 0;
}

三、类型转换的使用方法
注意:隐式类型转换一定要谨慎使用,从而避免产生错误的函数调用

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 我可以解释explicit构造函数的用法。 explicit构造函数C++中的一种特殊构造函数,它可以防止类的实例被隐式转换,从而避免出现错误。它通常被定义为一个具有const限定符的成员函数,这意味着它不能修改类的成员变量。 ### 回答2: 在C++中,构造函数被用于创建对象并初始化其成员变量。然而,有时我们可能希望禁止隐式地将某个类的一个参数类型转换为该类的对象类型,这时就可以使用explicit关键字来声明构造函数。 当我们使用explicit关键字声明一个构造函数时,它将不再能够进行隐式类型转换。只有在显式地调用构造函数时,才能使用该构造函数创建一个对象。 explicit关键字的使用可以避免一些潜在的问题和错误的发生。它可以防止编译器隐式地将一个参数类型转换对象类型,以免引发意想不到的结果。 举个例子,假设有一个类A,其中有一个带有一个int参数的构造函数。如果我们不使用explicit关键字来声明该构造函数,那么在编译器看来,一个int类型的变量可以被自动转换为一个A类型对象。这种隐式转换可能会导致意想不到的结果和错误的发生。 但是如果我们使用explicit关键字来声明该构造函数,那么编译器将不再允许隐式转换,只能通过显式调用构造函数来创建对象。 总之,explicit关键字用于禁止隐式地将一个参数类型转换对象类型。它可以避免潜在的问题和错误,使代码更加可靠和健壮。 ### 回答3: 在C++中,构造函数(Constructor)是一种特殊类型的成员函数,用于在创建对象时初始化对象的数据成员。当我们定义一个类时,可以定义一个或多个构造函数来满足不同的对象创建需求。其中,explicit是一个关键字,用于修饰构造函数。 explicit关键字的作用是防止隐式转换,它只能用于单参构造函数(即只有一个参数的构造函数)。当构造函数声明为explicit时,禁止编译器通过隐式转换将该参数类型转换成对应的类类型。可以通过显式方式调用构造函数进行对象的创建和转换。 举个例子,假设有一个类A,其中定义了一个单参构造函数A(int n),同时使用了explicit关键字进行修饰。如果没有explicit关键字修饰,则可以进行隐式转换,比如可以使用A对象去初始化一个int类型的变量。但是,如果使用explicit修饰之后,编译器将不再允许隐式转换,只能通过显式方式进行构造和转换。 这种explicit用法可以避免一些不必要的类型转换带来的错误和混淆,能够增加程序的类型安全性。此外,explicit关键字还可以用于拒绝编译器进行多次隐式转换,因为如果构造函数没有使用explicit关键字修饰,编译器可能会进行多次自动类型转换,导致程序的行为变得复杂和难以理解。 总结来说,当我们在定义构造函数时,如果希望限制使用隐式转换创建对象的情况,就可以使用explicit关键字对构造函数进行修饰,以保证程序的可读性和类型安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值