我是靠谱客的博主 重要手链,最近开发中收集的这篇文章主要介绍C++ keywork explicit,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

最近code的时候遇到一个warning,虽然不是error,但是也值得好好说一下:

Warning: Single-argument constructors must be marked explicit to avoid unintentional implicit conversions

在之前的文章中谈到了implicit conversion和operator conversion,似乎conversion是一件挺好的事情,可以帮助我们简化代码,提高效率。比如:

class entity{
	int m_age;
	std::string m_name;
public:
	entity(int age): m_age(age), name("unkown"){}
	entity(std::string name): m_age(0), m_name(name){}
};

int main(){
	// 我们可以直接这样来Initialize一个entity,让C++为我们完成implicit conversion
	// 而不必一定要写: entity e = entity(3);
	entity e = 3;
	return 0;
}

但是有时候,这种implicit conversion也会带来很多问题。
比如:

int main(){
	// correct
	entity e1 = 3;
	// error
	entity e2 = "Tom";
	return 0;
}

这种时候就会奇怪,为什么可以用entity e1 = 3,却不能用entity e2 = “Tom”,明明我们也有一个constructor entity(std::string name)。具体原因可以参见另一篇博文: C++ operator conversion

所以,什么时候source type才能安全转化为destination type? 什么时候source type被转化了?转化的时候调用了哪个method?

为了提高易读性,减少不必要的错误,在single-argument constructor中,我们应该尽量使用explicit keyword。

使用方法如下:

class entity{
private:
	int age;
    std::string name;
public:
    explicit entity(std::string& n):name(n), age(-1) {}

    explicit entity(int a):name("unknown"), age(a) {}
};

使用了explicit之后:

int main(){
	// error
	entity e1 = 3;
	// error
	entity e2 = "Tom"
	// correct
	entity e3("Tom");
	// correct
    entity e4(3);             
 }

explicit阻止compiler悄悄将某个我们不想要的类型转化成我们的目标类型。比如不能将int和const char*转化成entity。如果想要entity,必须调用constructor。

另外一个例子是:

struct A{};

struct B{
	// 这里会implicitly convert A to B
	B(A& a);
};

struct C{
	// 这里会implicitly convert C to B
	operator B();
};
 
// func 需要一个B类型的parameter
void func(const B& b);

int test(A& a, C& c){
	// implicitly convert type A to B using B::B(A& a)
	func(a);
	// implicity convert type C to B using C::operator B()
	func(c);
}

仅仅是这短短一段code,三个structs,就已经非常复杂,如果不仔细认真分析,很难知道底层究竟进行了什么转换。
而在实际code的时候,因为这种implicit conversion导致的错误是很难分析出来的。所以我们应该尽量使用explicit keyword。

struct A{};

struct B{
	// 这里会implicitly convert A to B
	explicit B(A& a);
};

struct C{
	// 这里会implicitly convert C to B
	explicit operator B();
};
 
// func 需要一个B类型的parameter
void func(const B& b);

int test(A& a, C& c){
	// explicit converion using B::B(A& a)
	func(B(a));
	// explicit conversion using C::operator B()
	func(static_cast<B>c);
}

B::explicit B(A& a)规定了不能将A类型隐形转换成B类型,除非显式调用B(A& a)
C::explicit operator B()规定了不能将C类型转化成B类型,除非显式调用static_cast

最后

以上就是重要手链为你收集整理的C++ keywork explicit的全部内容,希望文章能够帮你解决C++ keywork explicit所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部