Reputation:
consider following code
#include <iostream>
using namespace std;
class MyClass{
int a;
public:
MyClass(int j) {a = j;}
int geta(void) {return a;}
};
int main(void)
{
MyClass ob = 99;
cout << ob.geta();
}
output of this code is 99 my question is following statement MyClass ob is declare object of class MyClass and is allowed such kind of declaration that object is equal some number?maybe more specific declaration would be MyClass ob(99) what do you think?
Upvotes: 0
Views: 95
Reputation: 4163
You provided constructor taking an int. Without explicit
keyword it can be called implicitly - like here. If you would write MyClass ob(99)
, you would call this constructor explicitely. There is no difference until you declare constructor as explicit
. You would get compilation error when trying to assign an int to an object with explicit constructor.
EDIT: I checked - it is really using copy constructor too, as David and Alien01 said. It is just Visual Studio that doesn't follow the standard.
Upvotes: 3
Reputation: 208446
The general answer has already been provided by others, including @x13n. I will try to provide a little more detailed explanation of what the code really means.
The syntax MyObject ob = anotherMyObject;
is equivalent to MyObject obj( anotherMyObject );
. The meaning is copy construct ob
from the object anotherMyObject
. The compiler will always match MyObject ob = ...;
with a call to the copy constructor (usually MyObject( MyObject const &)
, but can also be MyObject( MyObject& )
if the user declares it as so).
In your particular code, the right hand side is not a MyObject
, so it cannot be passed as an argument to the copy constructor and the compiler will try to convert that rhs into something that can be used with the copy constructor of MyObject
applying the general rules. In your case, there is an implicit constructor that takes an int
argument, and that can be used to create a temporary MyObject
, so the compiler rewrites your code to be:
MyObject ob( MyObject( 99 ) );
// ^^^ temporary created by the compiler to match the copy constructor
Note that this is not the same as MyObject ob(99)
, but a combination of the int
and copy constructors, even if the overall effect is similar. If the constructor taking an integer was declared explicit
, then the compiler could not use it to provide the conversion and the code would fail to compile.
In a comment to another answer @x13n points out that this is not a call to the copy constructor, as if you add a trace to that constructor, the trace will not be generated. That is a completely different issue, where the compiler is able to optimize away the copy by creating the temporary in exactly the same address that ob
takes. There are two ways that this can be verified, both dependent on the fact that while the compiler can elide the copy it must adhere to the same restrictions. So we can make MyObject ob( MyObject(99) )
invalid in two ways, either disabling access to the copy constructor, or disabling the call to the constructor with a temporary:
class test1 {
test1( test1 const & ) {} // make the copy constructor private
public:
test1( int ) {}
};
class test2 {
public:
test2( test2 & ) {} // make the copy constructor take a non-const reference
// i.e. disable the use of temporaries
test2( int ) {}
};
int main() {
test1 t1 = 99; // copy constructor is private in this context
test2 t2 = 99; // g++: no matching function call to test2::test2(test2)
// diagnostics will differ with other compilers
}
Upvotes: 1
Reputation: 11349
When you are creating an object like
MyClass ob =99 ;
You are basically calling constructor of the class.
Same holds good when object is created as
MyClass ob(99);
In this case also ,constructor of class is called.
Upvotes: 2
Reputation: 2022
This is the interesting part:
MyClass(int j) {a = j;}
By default, a constructor with a single argument is implicit, which means the compiler automatically calls it wherever you want to assign an int
where a MyClass
is expected.
If you don't want this behaviour for your class, simply change the constructor to
explicit MyClass(int j) {a = j;}
And the behaviour is gone, now you need to explicitly (hence the keyword) call the constructor every time. Note that the explicit
keyword should only appear in the declaration in the class body, but not in an implementation outside of the body.
P.S.: This is, for example, how const char*
automatically becomes a std::string
when the latter is expected.
Upvotes: 2