概述
最近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所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复