Why Is There No Call to the Constructor

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:

  1. A object; calls the A::A() constructor. (The first "hello" is printed from here.)
  2. B bObject(object); will call the B::B(A) constructor, but because the A argument is accepted by value, object is first copied into a new, temporary A using the compiler-generated A::A(const A &) copy constructor.
  3. The B::B(A) constructor is called to create bObject, passing in the temporary A constructed in the last step.
  4. Inside of the B constructor, the B::object object is default-constructed using A::A() because it was not in the constructor's initializer list. (The second "hello" is printed from here.)
  5. Finally, the body of the B::B(A) constructor is run, which assigns the value of the temporary A object (stored in aObject) to the A contained in B::object, which was constructed in the prior step. This assignment is accomplished by using the compiler-generated A & 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:

  1. Name should match class name
  2. Constructor should not have a return type
  3. 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



Leave a reply



Submit