Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining an object without calling its constructor in C++

In C++, I want to define an object as a member of a class like this:

Object myObject; 

However doing this will try to call it's parameterless constructor, which doesn't exist. However I need the constructor to be called after the containing class has done some initialising. Something like this.

class Program { public:    Object myObject; //Should not try to call the constructor or do any initializing    Program()    {       ...        //Now call the constructor       myObject = Object(...);    }  } 
like image 483
Hannesh Avatar asked Sep 26 '11 15:09

Hannesh


People also ask

Can we create object without calling constructor?

Actually, yes, it is possible to bypass the constructor when you instantiate an object, if you use objenesis to instantiate the object for you. It does bytecode manipulations to achieve this. Deserializing an object will also bypass the constructor. It isn't possible to do this using reflection.

Can we create a dog object without using its constructor?

If we use the third constructor when we create the Dog object the breed and name fields are set to our desired values on one statement. If you omit a constructor, the Java compiler creates one for you internally. That default constructor has no parameters and no code so it really does nothing.

Can an object not have a constructor?

The constructors can be called explicitly or implicitly. The method of calling the constructor implicitly is also called the shorthand method. without any constructs (including default construct), objects cannot be created.

Can classes be defined without creating constructors?

Java doesn't require a constructor when we create a class. However, it's important to know what happens under the hood when no constructors are explicitly defined. The compiler automatically provides a public no-argument constructor for any class without constructors. This is called the default constructor.


2 Answers

Store a pointer to an Object rather than an actual Object

thus:

class Program { public:    Object* myObject; // Will not try to call the constructor or do any initializing    Program()    {       //Do initialization       myObject = new Object(...);  // Initialised now    }  } 

Don't forget to delete it in the destructor. Modern C++ helps you there, in that you could use an auto_ptr shared_ptr rather than a raw memory pointer.

like image 116
Julian Avatar answered Sep 16 '22 13:09

Julian


Others have posted solutions using raw pointers, but a smart pointer would be a better idea:

class MyClass {   std::unique_ptr<Object> pObj;   // use boost::scoped_ptr for older compilers; std::unique_ptr is a C++0x feature public:   MyClass() {     // ...     pObj.reset(new Object(...));     pObj->foo();   }   // Don't need a destructor }; 

This avoids the need to add a destructor, and implicitly forbids copying (unless you write your own operator= and MyClass(const MyClass &).

If you want to avoid a separate heap allocation, this can be done with boost's aligned_storage and placement new. Untested:

template<typename T> class DelayedAlloc : boost::noncopyable {   boost::aligned_storage<sizeof(T)> storage;   bool valid; public:   T &get() { assert(valid); return *(T *)storage.address(); }   const T &get() const { assert(valid); return *(const T *)storage.address(); }    DelayedAlloc() { valid = false; }    // Note: Variadic templates require C++0x support   template<typename Args...>   void construct(Args&&... args)   {     assert(!valid);     new(storage.address()) T(std::forward<Args>(args)...);     valid = true;   }    void destruct() {     assert(valid);     valid = false;     get().~T();   }    ~DelayedAlloc() { if (valid) destruct(); } };  class MyClass {   DelayedAlloc<Object> obj; public:   MyClass() {     // ...     obj.construct(...);     obj.get().foo();   } } 

Or, if Object is copyable (or movable), you can use boost::optional:

class MyClass {   boost::optional<Object> obj; public:   MyClass() {     // ...     obj = Object(...);     obj->foo();   } }; 
like image 45
bdonlan Avatar answered Sep 16 '22 13:09

bdonlan