單參數(shù)構(gòu)造函數(shù)的問題,single-argument construct
關(guān)于單一參數(shù)構(gòu)造函數(shù)的問題,主要是因?yàn)閱我粎?shù)被編譯器用作隱式類型轉(zhuǎn)換,從而導(dǎo)致一些不可預(yù)期的事件的發(fā)生,請參見代碼詳細(xì)注釋:
/* * single_argument_ctor.cpp * * Created on: 2010-3-29 * Author: Volnet * Compiler: GNU C++(version 3.4.5) * MSVC CL(version 15.00.30729.01) */ #include <stdlib.h> #include <iostream> #include <sstream> // single-argument class class SingleArgumentClass { private: int _inner; public: SingleArgumentClass() :_inner(-1) { } SingleArgumentClass(int actual) :_inner(actual) { } bool operator==(const SingleArgumentClass& rhs); std::string str(){ // we'd better to use boost::lexical_cast to cast. // #region cast std::stringstream strStream; strStream << _inner; std::string str; strStream >> str; // #endregion return str; } }; bool SingleArgumentClass::operator ==(const SingleArgumentClass& rhs){ if(_inner == rhs._inner) return true; return false; } // single-argument class fixed bug by explicit keyword. class SingleArgumentClassFixedBugByExplicitKeyword { private: int _inner; public: SingleArgumentClassFixedBugByExplicitKeyword() :_inner(-1) { } explicit SingleArgumentClassFixedBugByExplicitKeyword(int actual) :_inner(actual) { } bool operator==(const SingleArgumentClassFixedBugByExplicitKeyword& rhs); std::string str(){ // we'd better to use boost::lexical_cast to cast. // #region cast std::stringstream strStream; strStream << _inner; std::string str; strStream >> str; // #endregion return str; } }; bool SingleArgumentClassFixedBugByExplicitKeyword::operator ==(const SingleArgumentClassFixedBugByExplicitKeyword& rhs){ if(_inner == rhs._inner) return true; return false; } // single-argument class fixed bug by helper class. class ActualType { public: ActualType(int value):_value(value){}; int get_value(){ return _value; } private: int _value; }; class SingleArgumentClassFixedBugByHelperClass { private: int _inner; public: SingleArgumentClassFixedBugByHelperClass() :_inner(-1) { } SingleArgumentClassFixedBugByHelperClass(ActualType actual) :_inner(actual.get_value()) { } bool operator==(const SingleArgumentClassFixedBugByHelperClass& rhs); std::string str(){ // we'd better to use boost::lexical_cast to cast. // #region cast std::stringstream strStream; strStream << _inner; std::string str; strStream >> str; // #endregion return str; } }; bool SingleArgumentClassFixedBugByHelperClass::operator ==(const SingleArgumentClassFixedBugByHelperClass& rhs){ if(_inner == rhs._inner) return true; return false; } void Assert(bool status, std::string strTrue = std::string("assert result is true;"), std::string strFalse = std::string("assert result is false;")); int main(void){ SingleArgumentClass obj(3); std::cout << obj.str() << std::endl; // our purpose. SingleArgumentClass obj1(1); SingleArgumentClass obj2(1); Assert(obj1 == obj2, "obj1 == obj2", "obj1 != obj2"); int i = 3; // warning!!! // obj is a SingleArgumentClass object. // i is a integer. // operator== only define the equal between two SingleArgumentClass object. // In fact: // obj == i: // 1.compiler found the operator== require two SingleArgumentClass object. // 2.compiler try to find a cast method for casting int to SingleArgumentClass. // 3.compiler found it can use the SingleArguementClass.Ctor(int) // to create a new SingleArgumentClass. // 4.compiler try to create a new SingleArgumentClass object from i. // 5.so it without any warning and error, but it's logical not we need. Assert(obj == i, "obj == i //right?", "obj != i"); // Assert(i == obj); // Compile ERROR: no match for 'operator==' in 'i == obj' // it's may encounter a compile-time error. // GNU G++: no match for 'operator==' in 'objFixed == i' single_argument_ctor.cpp single_argument_ctor/src 106 C/C++ Problem // MSVC: 錯(cuò)誤 1 error C2679: 二進(jìn)制“==”: 沒有找到接受“int”類型的右操作數(shù)的運(yùn)算符(或沒有可接受的轉(zhuǎn)換) {projectpath}\single_argument_ctor\src\single_argument_ctor.cpp 107 single_argument_ctor SingleArgumentClassFixedBugByExplicitKeyword objFixed(3); // Assert(objFixed == i, "objFixed == i", "objFixed != i"); SingleArgumentClassFixedBugByHelperClass objFixedByHelper1(3); SingleArgumentClassFixedBugByHelperClass objFixedByHelper2(3); // it's may encounter a compile-time error. // GNU G++: no match for 'operator==' in 'objFixedAuto1 == i' single_argument_ctor.cpp single_argument_ctor/src 158 C/C++ Problem // MSVC: 錯(cuò)誤 1 error C2679: 二進(jìn)制“==”: 沒有找到接受“int”類型的右操作數(shù)的運(yùn)算符(或沒有可接受的轉(zhuǎn)換) {projectpath}\single_argument_ctor\src\single_argument_ctor.cpp 163 single_argument_ctor // Assert(objFixedByHelper1 == i); } void Assert(bool status, std::string strTrue, std::string strFalse) { std::cout << (status strTrue : strFalse) << std::endl; }
解決方法:
1、explicit關(guān)鍵字,在單參數(shù)構(gòu)造函數(shù)前使用explicit參數(shù),可以避免單參數(shù)構(gòu)造函數(shù)被用于隱式轉(zhuǎn)換。
2、利用中間類的方式,詳見代碼“SingleArgumentClassFixedBugByHelperClass相關(guān)部分”。如果編譯器不支持解決方法1,則建議使用此方法。上面代碼所提及的兩款主流編譯器均支持explicit關(guān)鍵字。
posted on 2010-03-29 15:37 volnet 閱讀(1883) 評(píng)論(0) 編輯 收藏 引用 所屬分類: C/C++