The C++ is designed in such a way that by default,a single argument constructor also defines an implicit conversion. In C++, an implicit conversion is a conversion from one type to another that doesn't require an explicit typecast. For example consider following class:
class Conversion {
To prevent above discussed problem C++ comes up with explicit keyword, that suppressed the implicit conversion. That is, an explicit constructor will be invoked only explicitly. So if we modify above class declaration as follow:
Now for line
We will get compiler error since there's no implicit conversion from char to int. How ever we can still write
class Conversion {
public:
Conversion(int o=0) : data(o) { }
int getData() { return data;}
private:
int data;
};
int main(){
Conversion c = 5; // initialize c with Conversion(5)
cout << c.getData() << endl;
return 0;
}
Here the constructor worked as implicit converter.
But there are cases where this feature can play bad. Consider following:
class MyString { public: MyString(const char* str); // initial val is c-style string str MyString(const int len=0); // pre-allocate len bytes const char* getData() const { return c;} private: char *c; unsigned int len; }; MyString::MyString(const int len) { this->len=len; c= new char[len+1]; } MyString::MyString(const char *str) { len = strlen(str); c = new char[len+1]; strcpy(c, str); } int main() { MyString m_str = "it works here"; //MyString(const char *str) cout << m_str.getData()<< endl; MyString m_str2 = 'a'; //MyString(const int len) cout << m_str2.getData() << endl; return 0; }
Now, MyString m_str2 = 'a'; makes m_str2 a string with 'a' char, its quite unlikely
that this is what person want. So make sure that the conversion is intuitive and
consistent with major C++ conventions. If not, consider using non-constructor member functions.
To prevent above discussed problem C++ comes up with explicit keyword, that suppressed the implicit conversion. That is, an explicit constructor will be invoked only explicitly. So if we modify above class declaration as follow:
class MyString { public: MyString(const char* str); // initial val is c-style string str explicit MyString(const int len=0); // pre-allocate len bytes const char* getData() const { return c;} private: char *c; unsigned int len; };
Now for line
MyString m_str2 = 'a';
We will get compiler error since there's no implicit conversion from char to int. How ever we can still write
MyString m_str2(10);
Which is what we were trying to accomplish in the first place.
When designing classes, if you have a single-argument constructor that is not intended
as a conversion function, you must mark it explicit to avoid running into the “implicit conversion” trap.
No comments:
Post a Comment