0
Explicit constructor
Hi Refer below code : https://code.sololearn.com/cAJm3OyxMyzv/?ref=app Constructor is explicit in this case. Removing this keyword make code work perfectly fine... If everything is fine, what is the reason to have explicit constructor and restricting the way it is already working
18 ответов
+ 1
Let's take a more concrete example. Say you have a class `Array` and the integer parameter is `length`. Then why should a cast from int to Array like this even be possible?
`Array a = 4;` does not seem right.
Weak typing is the source of all evil, we know it from javascript, and C++ already has complicated enough implicit conversion rules: https://en.cppreference.com/w/cpp/language/implicit_conversion
Constructors are probably less of an issue but the type casting functions `operator T () { ... }` should always be explicit, in my opinion. Otherwise implicit casts will happen and you won't notice and you spend time debugging that a simple compiler error could have prevented.
I don't think "implicit" constructors are much of feature. Or anyway, explicit should be the default, and there should be an `implicit` keyword that gives you implicit casting behaviour.
EDIT: Here's a classic example of the "I did not notice a conversion is happening" phenomenon:
https://code.sololearn.com/c5w3rs4iqtc6/?ref=app
+ 3
Ketan Lalcheta Explicit constructors are important in preventing implicit conversions from occurring.A constructor that takes only one argument is known as a conversion constructor since it basically converts the object given as the arguments of to your own user-defined type.In your case,all objects of type int are converted to Test using the conversion constructor that you provided Test(int ii);
Your code compiles once you eliminate the keyword explicit since the int 1 is first converted IMPLICITLY by the compiler to a temporary object of type Test which is then assigned to a.
Now,this kind of implicit conversion is at times useful for example in the case of string and complex classes but in most cases it can be a source of subtle errors.
To prevent this the keyword explicit was created so as to prevent the compiler from converting the object given in the argument,to your own user defined type.It forces you,the programmer to initialize an object explicitly if you want to use it.
+ 3
Schindlabua Implicit conversion is a useful feature in some classes like string and complex.
Consider a function like this:
void func( string a);
string's constructor is not explicit,therefore you can call func in this manner and you won't get an error.
func("hello world").
This agrees with our intuitive notion of a string.We can seamlessly use const char* types(C-style strings) and strings(C++ strings) interchangeably without experiencing a lot of difficulty.
If string's constructor was explicit,we would be forced to call the func function like this
func(string{"hello world"});
This is not only confusing to most people,but is also likely scare newbie C++ programmers.Thus implicit conversion is an invaluable tool that cannot be simply disregarded and thrown away.
+ 3
Schindlabua I think the reason as to why all constructors are not explicit by default has something to do with the compilation process.I tend to think it would be highly inefficient for the compiler to keep on checking whether an object has been initialized in the correct way.
Take a moment and think about this.
In your example,even though a call like b.foo(4) is correct,not many people(maybe even no one) would do this.Many people would pass an already existing A object,let's say obj like this
b.foo(obj);
So if explicit was the default the compiler would have to do a lot of redundant checks to safeguard against an error,even though it may be subtle,does not occur very often.Thus increasing the compilation time
+ 2
Hey Ketan Lalcheta , ya it's necessary to keep explicit keyword here but, the playground might be designed to compile these type of programs without any explicit type cast ..if you want to keyword explicit really then go for some other compilers like codeblocks, Device c++ etc..
I think in that platforms you are required to use explicit keyword.
I think this might help you
https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/rzarg/explicit_conversion_constructors.htm
+ 2
Hi Nikhil Maroju , sololearn app's compiler also throw error with constructor marked as explicit.
In existing code , try removing explicit keyword and compile...it works.
My concern is why to use explicit keyword itself... Without using it, constructor is called properly and object getting constructed is used to call method of class.
What is harm which prevents explicit keyword by marking constructor explicit
+ 2
For your code to work,you have to explicitly initialize variable a using either () or {} like this
Test a(1); or Test a{1};
Note that for you to use the assignment operator you also have to explicitly create a temporary Test object first then assign it to a like this
Test a=Test{1};
+ 2
Anthony Maina Yep, fair.
But I see it like `const`: If everything was const-by-default, we wouldn't have to drill programmers to be const-correct and a whole class of bugs would be eliminated right there. (Rust has a `mut` keyword for mutability).
Similarly "implicit" constructors should be opt-in, not opt-out. You don't need them a whole lot but the resulting bugs can be pretty annoying.
+ 2
I have no specific answer for that really.
All I can say is that all programmers are stupid and we will forget things two seconds after we wrote them, like goldfish. Then you have to go and remind yourself: What was the function signature again?
void foo(A const& a);
ah.
But you forget that there are ten other classes that implicitly convert to `A` and so occasionally you end up constructing objects you didn't mean to construct. And that can have all sorts of side effects.
Like, programmers are stupid, and it will happen that there is a method that takes `A`, but you give it `int`, because the method doesn't do what you think you remember it does. And then implicit conversion makes the program compile regardless and you spend an hour digging through your project because of some obscure bug.
And those bugs are the worst because that's the last place you check.
Totally avoidable too if you had just marked all your constructors explicit, it takes 0 effort, meanwhile debugging makes you age 5x as fast.
+ 2
Ketan Lalcheta I asked that in the ##c++ chat on freenode IRC a while back, and while everyone agreed it's good practice very few people actually did it. ¯\_(ツ)_/¯
If I had to write a serious C++ project I would definitely take the time to mark constructors as explicit.
But it's not a huge deal I guess.
+ 2
Thanks Schindlabua and Anthony Maina for your time and effort to make me understand... Appreciate your responses 👍
+ 2
Anthony Maina I'm not sure about that!
Anytime a call like `b.foo(4)` happens, the compiler will say "Okay, this 4 here is not an `A`. Is there a way to implicity convert `int` to `A`, like an implicit constructor, so I can make this program typecheck?"
And the answer to that is either yes or no, but the compiler will need to check either way.
That's my guess anyway.
+ 1
Schindlabua nice explanation..I got your point..that you are allowed to pass int which inturn gets converted to class type implicitly.
But my issue is something different....even if compiler manage it, what is wrong ?
Consider below code updated from your code:
#include <iostream>
using namespace std;
struct A {
A () { }
A (int a) { }
void display () const
{
cout << "Hi frm B by A";
}
};
struct B {
B () { }
void foo (A const& a) {
cout << "You gaves me an A! :))";
a.display();
}
};
int main() {
B b;
b.foo(4);
return 0;
}
Here, 4 passed as int converted to class A Obj and without error it used to call display method... What's wrong then? Why to block this by declaring explicit... I am convinced that it avoids some debug issues by giving compiler error , but I can't decide such case and that is what I am looking for... Hope it makes sense to ask this question
+ 1
Okay Schindlabua , I do agree the pain of debugging if something goes wrong...
Does this mean we as a better practice should mark all constructor of our own classes as explicit? If so, doesn't it a good improvement to have constructor definition by default as explicit?
+ 1
Schindlabua I also think that this is also the same reason as to why all variables are not constant by default.If come to think of it,you only need a variable to be constant when you do not have full control over it e.g in the case of global variables.
But for local variables you really don't have to worry since there are many other far important and indisposable mechanisms e.g pass-by-value(should you want to pass it to a function) to protect it from unpredictable change.
Making all variables const would place a heavy burden on the compiler since the redundant checks to ensure that a variable is not changed would be too many.
0
It's a pain you need to have lived through :D
Maybe I can come up with an example.
0
Schindlabua
/*
Anthony Maina I'm not sure about that!
Anytime a call like `b.foo(4)` happens, the compiler will say "Okay, this 4 here is not an `A`. Is there a way to implicity convert `int` to `A`, like an implicit constructor, so I can make this program typecheck?"
And the answer to that is either yes or no, but the compiler will need to check either way.
That's my guess anyway.
*/
Yeah Maybe