Calling the constructor of a potential child from the base in C ++

How can someone implement this template:

class Base {//doesn't know anything about potential descendant-classes, like Child public: Base * foo( void) { //some code return ( Base *) new !Child-constructor!(); } }; class Child : public Base { }; //————————————————————————————————————————————————— #include <iostream> #include <typeinfo> using namespace std; int main( void) { Base * base_p = Child().f(); cout << typeid( *base_p).name(); //expected to get "Child" return 0; } 

I can not find the correct syntax for this type of constructs (calling the "potential" child constructor).

UPD : I forgot to mention (I didn’t think there could be a misunderstanding) that the Child class should not be known in the Base definition. Therefore, I wanted foo call the constructor of the class into which it is inherited.

+1
source share
3 answers

"... that the Child class should not be known in the Base definition. Therefore, I wanted foo to call the constructor of the class in which it is inherited."

IMHO the easiest way is a templated factory function with Base

 class Base { public: template<class Derived> static std::unique_ptr<Base> foo( void) { //some code return std::unique_ptr<Base>(new Derived()); } }; class Child : public Base { public: Child() {} virtual ~Child() {} }; int main() { std::unique_ptr<Base> p = Base::foo<Child>(); return 0; } 

Check the compiled sample here .

+1
source

This design is terrible, by the way.

  //terriblecode.hpp struct Base { Base * foo(void); }; struct Child : public Base{}; //terriblecode.cpp Base* Base::foo() {return (Base*) new Child();} 

The definition of a child is not required before the definition of foo. Separate your declaration from the definition of member functions, and this is pretty easy to do.

0
source

Just make sure you tell the compiler about your derived class before first use:

 class Child; // forward declaration class Base { public: Base * foo( void); }; class Child : public Base { }; // the function needs to be defined after the "Child" is known Base * Base::foo( void) { //some code return new Child; // will be automatically type-cast to base class } //————————————————————————————————————————————————— #include <iostream> #include <typeinfo> using namespace std; int main( void) { Base * base_p = Child().f(); cout << typeid( *base_p).name(); //expected to get "Child" return 0; } 

However, I would recommend a different template:

 class Child; // forward declaration class Base { public: static Base * foo( void); // static "factory" method }; class Child : public Base { }; // the function needs to be defined after the "Child" is known Base * Base::foo( void) { //some code return new Child; // will be automatically type-cast to base class } //————————————————————————————————————————————————— #include <iostream> #include <typeinfo> using namespace std; int main( void) { Base * base_p = Base::f(); // use scope resolution, not object method cout << typeid( *base_p).name(); //expected to get "Child" return 0; } 
0
source

Source: https://habr.com/ru/post/972427/


All Articles