CppCoreGuidelines C.164 避免隐式的转换操作
19 January 2023
“Avoid implicit conversion operators”
理由
隐式转换有时候是必不可少的(如 double 转成 int),但是经常导致意想不到的结果(如 String 转成 C 风格的 string)。
注意
尽量使用显示的类型转换,除非特殊情况使用隐式转换。不要因为方便而选择隐式转换。
例子
struct S1 { string s{"S1"}; // ... operator char*() { return s.data(); } // BAD, likely to cause surprises }; struct S2 { string s{"S2"}; // ... explicit operator char*() { return s.data(); } };
struct S1 { string s{"S1"}; // ... operator char*() { return s.data(); } // BAD, likely to cause surprises }; struct S2 { string s{"S2"}; // ... explicit operator char*() { return s.data(); } }; void f(S1 s1, S2 s2) { char* x1 = s1; // OK, but can cause surprises in many contexts cout << x1 << endl; //char* x2 = s2; // error (and that's usually a good thing) char* x3 = static_cast<char*>(s2); // we can be explicit (on your head be it) cout << x3 << endl; } int main() { S1 s1; S2 s2; f(s1, s2); }
S1 S2
因为转换操作符添加了 explicit,所以需要进行显式的转换。
struct S1 { string s{"S1"}; // ... operator char*() { return s.data(); } // BAD, likely to cause surprises }; struct S2 { string s{"S2"}; // ... explicit operator char*() { return s.data(); } }; void f(S1 s1, S2 s2) { char* x2 = s2; // error (and that's usually a good thing) } int main() { S1 s1; S2 s2; f(s1, s2); }
C-src-gvvjq1.cpp: In function 'void f(S1, S2)': C-src-gvvjq1.cpp:23:16: error: cannot convert 'S2' to 'char*' in initialization 23 | char* x2 = s2; | ^~ | | | S2
不然编译器就会报错,说无法进行转换。
隐式类型转换会引起意想不到的结果,和潜在的破坏。而且还很难发现。
比如
S1 ff() {}; char* g() { return ff(); }
ff() 返回的字符串在使用内部指针之前可能就已经被销毁。
强化
- 标注使用非显式转换的操作。