Is it possible to create an instance of a class inside one class?

Let's say I have a class:

class Foo{ public: Foo(){ } //Is it possible to create a function like this: virtual Foo* createOb(){ //Should create a new Foo,Bar or Fiz, depending on the actual object type. } } class Bar: public Foo{ public: Bar(){ } } class Fiz: public Foo{ public: Fiz(){ } } 

Is it possible to have the createOb() method in the base class, so when createOb () is called on an instance of one of the derived classes, an instance of the derived class is created?

+7
c ++ c ++ 11
source share
4 answers

Yes, this can be done using CRTP .

At first, returning the original pointer obtained from new is very dangerous . In c++ raw pointers should only be used when they do not have ownership of the pointed object. So I took the liberty of using unique_ptr :

 struct Base { virtual auto create_obj() -> std::unique_ptr<Base> { return std::unique_ptr<Base>{}; } }; // abstract works too: struct Base { virtual auto create_obj() -> std::unique_ptr<Base> = 0; }; template <class Derived> struct Base_crtp : Base { auto create_obj() -> std::unique_ptr<Base> override /* final */ { return std::unique_ptr<Base>{new Derived{}}; } }; struct D1 : Base_crtp<D1> { }; struct D2 : Base_crtp<D2> { }; 

And then:

 auto b1 = std::unique_ptr<Base>{new D1{}}; auto b2 = std::unique_ptr<Base>{new D2{}}; auto new_d1 = b1->create_obj(); auto new_d2 = b2->create_obj(); 
+5
source share

Definitely yes!!!

When a method is declared virtual in the base class and is called through the object of the derived class, then the function of the derived class is called (Read vprt, vtable concept in C ++).

 #include <iostream> using namespace std; class A{ public: virtual A* getobj(){ return new A(); } }; class B: public A{ public: B(){cout<<"B constructor"<<endl;} virtual A* getobj(){ return new B(); } }; int main() { A *a = new B(); A *second = a->getobj(); return 0; } 

In the above code, we call the getobj () function using an object of class B. Here, the constructor of class B is called twice.

  • first, for the new B () in the main

  • secondly, to call the getobj function, which again creates an object B

+1
source share

No, this is not possible with pure inheritance. Classes must override the createOb() member createOb() to support cloning.

You can understand why this is not possible by considering a separate class compilation. The implementation of the one-fits-all createOb() member function must be performed in isolation from Bar and Fiz , which makes it impossible for the database to know the type of its subclasses.

An implementation with a pure virtual function in the database is very common.

Another approach is to use the Curiously Recurring Template Pattern (CRTP) to implement cloning. This article explains how to do this.

0
source share

This is not an optimal solution, but it works.

In your .h

 class Foo{ public: Foo(); virtual Foo* createOb(); }; class Bar: public Foo{ public: Bar(); }; class Fiz: public Foo{ public: Fiz(); }; 

In your .cpp

 #include "Header.h" Foo::Foo() {} Foo* Foo::createOb(){ if (dynamic_cast<Bar*>(this)) { return new Bar(); } else if (dynamic_cast<Foo*>(this)) { return new Foo(); } return nullptr; } Bar::Bar() {} Fiz::Fiz() {} 

As already mentioned, consider a pure virtual method

0
source share

All Articles