【C++】类的隐式转换和explicit抑制类的隐式转换

2023年8月5日,周六下午

今天在网上找了很久都没找到有精确定义了类的隐式转换条件的资料,最后是在权威书籍《C++ Primer(第5版)》里面找到的。

说真的,虽然我认为《C++ Primer(第5版)》不适合作为新手学习C++的教材,因为内容太多了,很多只有你真正遇到才会看懂,但是《C++ Primer(第5版)》非常适合拿来做一本深入学习或者精确理解某个知识点的含义的参考书,建议想深入学习C++的人要有一本。


目录

  • 类的隐式转换的条件 
  • 举段代码来说明
  • 单参数构造函数实现类的隐式转换
  • 多参数构造函数实现类的隐式转换
  • 什么是explicit
  • 为什么需要explicit

类的隐式转换的条件 

能通过一个实参调用的构造函数定义了一条从构造函数的参数类型向类类型隐式转换的规则。——C++ Primer(第5版)

举段代码来说明

单参数构造函数实现类的隐式转换

#include 

class A {
	
private:
    int _value;

public:
    A(int value) : _value(value) {}  // 转换构造函数

    int getValue() const {
        return _value;
    }

};

void printValue(const A& obj) {
    std::cout << obj.getValue() << std::endl;
}

int main() {
	A a(10);
	printValue(a);
	
	//本来函数printValue需要一个A类的对象作为实参才能调用
	//但是现在只输入了一个int型的实参就成功调用了
	//也就是说,编译器自动完成了从int型到A类的转换
    printValue(5);

    return 0;
}

多参数构造函数实现类的隐式转换

并不是说,不是单参数的构造函数就不能实现类的隐式转换:在多参数构造函数中,如果所有的形参都有默认值或者只有第一个形参没有默认值而其他形参都有默认值,那么也是可以实现类的隐式转换的,因为归根到底这些构造函数只需一个实参就能调用。

现在举代码来说明:

#include

class A_point{
	
public:
	int _x,_y;
	//构造函数有多个形参,且都有默认值
	A_point(int x=0,int y=0):_x(x),_y(y){}
};

class B_point{
	
public:
	int _x,_y;
	//构造函数有多个形参,且只有第一个没有默认值
	B_point(int x,int y=0):_x(x),_y(y){}
};

void printA_point(const A_point& a){
	std::cout <<"("<

什么是explicit

简单来说,explicit就是禁止类的隐式转换的:

如果给上面的三个类的构造函数前面都加上explicit关键字,

explicit A(int value) : _value(value) {} 

explicit A_point(int x=0,int y=0):_x(x),_y(y){}

explicit B_point(int x,int y=0):_x(x),_y(y){}

那么都会在打印函数部分报错,因为再也无法通过隐式转换变成相应的类的对象,

printValue(5);

printA_point(1);

printB_point(2);

只能老老实实调用类的构造函数

printValue(A(5));

printA_point(A_point(1));
printA_point(A_point(1,2));

printB_point(B_point(2));
printB_point(B_point(2,3));

为什么需要explicit

尽管类的隐式转换可以使代码更加灵活,但过度使用可能会导致代码难以理解和维护,因为这样的灵活意味着不确定性,意味着即使是错误的、无意义的转换也可能会被允许。

#include

class A_point{
	
public:
	int _x,_y;
	//构造函数有多个形参,且都有默认值
 	A_point(int x=0,int y=0):_x(x),_y(y){}
};


void printA_point(const A_point& a){
	std::cout <<"("<

如果加上了explicit,那么这两个printA_point会报错

你可能感兴趣的:(我的博客,c++,开发语言)