Why can I not call my class's constructor from an instance of that class in C++?
By definition, a constructor is only called once, when the object is created. If you have access to an object, then it must have been created, so you're not allowed to call the constructor again - this is the reason why explicit constructor calls are not allowed. Similarly, destructors must only be called once, when the object is destroyed. If this could always done automatically, then the language would also forbid explicit destructor calls.
However, in some circumstances, you might want precise control over memory management, and the ability to explicitly create and destroy objects within memory that you are managing. For this purpose, the language provides "placement new" to create an object at an arbitrary location, and explicit destructor calls to destroy objects created this way. An explicit constructor call wouldn't be useful, since you need to be able to specify the location of the new object - so you get "placement new" instead. An explicit destructor call is sufficient, so there's no need to invent some sort of matching "placement delete".
So: there is no valid use for explicit constructor calls, so they are not allowed. There is a valid use for explicit destructor calls, so they are (syntactically) allowed, with the rule that you must only ever use them on objects that won't otherwise be destroyed, i.e. objects created using "placement new", and in that case call them exactly once. Using them in any other way, like so many C++ errors, will compile but give undefined behaviour.
when are constructors called and how to not call them
This happens because your B
class contains a member of type A
. As part of the construction of B
, the B::object
member is constructed, which requires a call to the A
constructor. So you actually have two A
instances: object
and bObject.object
.
Because you did not put object
in B::B()
's initializer list, B::object
is default-constructed. object = aObject;
then assigns to the existing A
stored in object
. So rather than copy-constructing B::object
, you default-construct it (which is responsible for the second "hello" you see) and then you assign a new value to it.
The compiler will provide a copy-constructor A(const A &)
for you, so you can copy-construct B::object
from the parameter like so:
B(A aObject) : object(aObject) { }
This constructor does not call the default constructor, nor does it contain the code contained in the default constructor. Therefore, calling this constructor does not cause output of "hello".
Note that you would still be constructing a new A
(in fact you would be doing so twice, because aObject
is passed by value) but since you did not define the copy-constructor yourself, it wouldn't contain your code that writes a string to std::cout
.
The actual sequence of relevant events that happen here is:
A object;
calls theA::A()
constructor. (The first "hello" is printed from here.)B bObject(object);
will call theB::B(A)
constructor, but because theA
argument is accepted by value,object
is first copied into a new, temporaryA
using the compiler-generatedA::A(const A &)
copy constructor.- The
B::B(A)
constructor is called to createbObject
, passing in the temporaryA
constructed in the last step. - Inside of the
B
constructor, theB::object
object is default-constructed usingA::A()
because it was not in the constructor's initializer list. (The second "hello" is printed from here.) - Finally, the body of the
B::B(A)
constructor is run, which assigns the value of the temporaryA
object (stored inaObject
) to theA
contained inB::object
, which was constructed in the prior step. This assignment is accomplished by using the compiler-generatedA & A::operator=(A const &)
operator.
Why explicitly call a constructor in C++
Most often, in a child class constructor that require some parameters :
class BaseClass
{
public:
BaseClass( const std::string& name ) : m_name( name ) { }
const std::string& getName() const { return m_name; }
private:
const std::string m_name;
//...
};
class DerivedClass : public BaseClass
{
public:
DerivedClass( const std::string& name ) : BaseClass( name ) { }
// ...
};
class TestClass :
{
public:
TestClass( int testValue ); //...
};
class UniqueTestClass
: public BaseClass
, public TestClass
{
public:
UniqueTestClass()
: BaseClass( "UniqueTest" )
, TestClass( 42 )
{ }
// ...
};
... for example.
Other than that, I don't see the utility. I only did call the constructor in other code when I was too young to know what I was really doing...
Spring not calling the default constructor
A constructor in Java should have following rules:
- Name should match class name
- Constructor should not have a return type
- compiler generates default constructor if there is no explicit declaration(user written constructor that looks exactly like a default one is not called default constructor)
In your code you have added return type which makes it a method , since there is no constructor written it is calling a default constructor generated by the compiler.
public Student(){
id = 1;
name="asd";
}
Removing void
should fix the issue ,however this is a user defined constructor
Why it is not a good idea to call Set method from constructor?
It is very true.
Because setters are always public
methods. And if you class is not final
then there is issue of alien method call. Which is not thread safe i.e. it is known as escaping of this
reference. So from a constructor if you are calling a method it should be final
or private
. Else safe initialization
of object will not happen which causes many bugs in real systems.
Apart from the above we should never call public
method from the constructor
because if the class is intended for inheritance than Constructors must not invoke overridable methods, directly or indirectly.
If you violate this rule, program failure will result. The superclass constructor runs before the subclass constructor, so the overriding method in the subclass will be invoked before the subclass constructor has run. If the overriding method depends on any initialization performed by the subclass constructor, the method will not behave as expected.
source.
Can you call the destructor without calling the constructor?
Yes, the destructor is nothing more than a function. You can call it at any time. However, calling it without a matching constructor is a bad idea.
So the rule is: If you did not initialize memory as a specific type, you may not interpret and use that memory as an object of that type; otherwise it is undefined behavior. (with char
and unsigned char
as exceptions).
Let us do a line by line analysis of your code.
test* array = (test*)malloc(3 * sizeof(test));
This line initializes a pointer scalar array
using a memory address provided by the system. Note that the memory is not initialized for any kind of type. This means you should not treat these memory as any object (even as scalars like int
, let aside your test
class type).
Later, you wrote:
std::cout << array[i].num << "\n";
This uses the memory as test
type, which violates the rule stated above, leading to undefined behavior.
And later:
(array + i)->~test();
You used the memory a test
type again! Calling destructor also uses the object ! This is also UB.
In your case you are lucky that nothing harmful happens and you get something reasonable. However UBs are solely dependent on your compiler's implementation. It can even decide to format your disk and that's still standard-conforming.
Related Topics
Which Is the Fastest Algorithm to Find Prime Numbers
How to Use Boost in Visual Studio 2010
Significance of Ios_Base::Sync_With_Stdio(False); Cin.Tie(Null);
When Should I Make Explicit Use of the 'This' Pointer
Constructor Initialization-List Evaluation Order
How to Implement the Factory Method Pattern in C++ Correctly
Why Is Transposing a Matrix of 512X512 Much Slower Than Transposing a Matrix of 513X513
How to Create a Generic Object Model For Use in Qml
Rotating a Point About Another Point (2D)
Forward Declaring an Enum in C++
C++0X Has No Semaphores? How to Synchronize Threads
Does the Size of an Int Depend on the Compiler And/Or Processor
Example For Boost Shared_Mutex (Multiple Reads/One Write)