Lakshmi
Lakshmi

Reputation: 1809

Can you invoke an instantiated object's class constructor explicity in C++?

After creating a instance of a class, can we invoke the constructor explicitly? For example

class A{
    A(int a)
    {
    }
}

A instance;

instance.A(2);

Can we do this?

Upvotes: 11

Views: 13389

Answers (7)

Michael Platings
Michael Platings

Reputation: 3165

You can use placement new, which permits

new (&instance) A(2);

However, from your example you'd be calling a constructor on an object twice which is very bad practice. Instead I'd recommend you just do

A instance(2);

Placement new is usually only used when you need to pre-allocate the memory (e.g. in a custom memory manager) and construct the object later.

Upvotes: 15

Shadow
Shadow

Reputation:

No you cannot do that. The only way to invoke a constructor is by the keyword "new".

Upvotes: 0

orcmid
orcmid

Reputation: 2638

Just to summarize, the three ways to specify the explicit constructor are via

  1. A instance(2); // does A instance = 2; ever work?

  2. A *instance = new A(2); //never sure about & versus * here, myself

  3. new (&instance) A(2);

and flavors of those. The idea goal is to arrange that at no time is an object constructed that is not in a proper initialized state, and constructors are designed to assure that. (This means that methods don't have to check on whether some .init(...) method has been successfully called or not.)

This strikes me as the more-functional way to go about this, especially for classes that are parts of frameworks and reused in libraries. If that is what you are interested in, work toward having all constructors, including any default one, deliver a fully-working instance.

Exception Cases: There are things you might not have in the constructor operation if it is possible for them to fail, unless it is appropriate to throw an exception from the constructor. And some folks like having "blank" instances that are propogated using subsequent methods and even exposed-to-initialization members. It is interesting to explore ways to mitigate such situations and have robust instances that don't have bad states that need to be protected against in method implementations and in usage.

PS: In some complex cases, it may be useful to have an initialized instance (reference) be delivered as the result of a function or of a method on a "factory" class, so that the intermediate, under-setup instance is never seen outside of the encapsulating factory class instance or function. That gives us,

+4. A *instance = MakeAnA(2);

+5. A *instance = InterestingClass.A(2);

Upvotes: -1

Konrad Rudolph
Konrad Rudolph

Reputation: 545588

By the way, this sounds like a design flaw. Once an object is constructed there should never be a need to re-construct it. Such variable name reuse makes the code rather harder to understand. For that reason, making constructor-like functionality available through an extra function init or set is often wrong (but sometimes unavoidable).

As Michael said, placement new could be used here but is really intended for different uses. Also, before constructing a new object in a memory location, you have to explicitly destroy the old object:

instance.~A();

Also, placement new can have an averse effect on your memory because overloads might expect that the memory it is passed belongs to the heap! In conclusion: don’t. do. this.

EDIT To demonstrate that calling the destructor is really necessary (for non-POD), consider the following example code:

#include <iostream>

struct A {
    A(int a) { std::cerr << "cons " << a << std::endl; }
    ~A() { std::cerr << "dest" << std::endl; }
};

int main() {
    A instance(2);
    new (&instance) A(3);
}

As expected, the program results in the following output:

cons 2
cons 3
dest

… which means that the destructor for the first object is not called. The same goes for any resources that A might have acquired.

Upvotes: 1

yesraaj
yesraaj

Reputation: 47900

No

Calling instance.A() or A(1) is seens as casting  'function-style cast' : illegal as right side of '.' operator

Usually if a function/functionality is to needed in constructor as well as after object is construted it is placed in init() methode and used in constructor and in other place too.

example:

 class A{
      A(int a)
       { 
        init(a);
       }

     void init(int a) { } 
     }

        A instance;

        instance.init(2);

Upvotes: 4

brofield
brofield

Reputation: 2286

No.

Create a method for the set and call it from the constructor. This method will then also be available for later.

class A{
    A(int a) { Set(a); }
    void Set(int a) { }
}

A instance;

instance.Set(2);

You'll also probably want a default value or default constructor.

Upvotes: 10

Paul Kapustin
Paul Kapustin

Reputation: 3295

I am pretty sure you can't do that. That's the whole point, constructor IS creation of an instance of the class.

If a constructor is not called at all, or is called twice - which consequences could it have?

What you could do of course, is extracting some constructor logic into the method, and calling that method both in the constructor and after creation of the object.

Upvotes: 3

Related Questions