I am faced with a situation, where I would like to call a virtual method from the constructor. This is of course not possible (or at least it does not produce the desired behavior). In this answer as a work-around it is proposed to use a factory method. I wrote something like this:
#include <iostream>
class Base {
public:
Base(){}
~Base(){}
// private: ??
virtual void afterConstruction()=0;
};
class Derived : public Base {
public:
Derived() : Base() {}
//private: ??
void afterConstruction(){std::cout<<"construct"<<std::endl;}
};
template <typename T> T MyFactory(){
T t = T();
T* p = &t;
p->afterConstruction();
return t;
}
int main(int argc, char** argv) {
Derived d = MyFactory<Derived>();
return 0;
}
It is kind of a template method pattern. Each derived class can customize the way it is constructed. However, this whole construct only makes sense, when a user of this classes cannot call the constructor or the afterConstruction()
directly. Thus I would like to have both of them private. Maybe it is a stupid question and I just do not see the obvious. Maybe I can achieve this by using friendship or something like that, but I am not sure if this is the best way. What is a nice and clean way to hide this two methods and only allowing to create object via the factory method?
EDIT: Ka7Im1011 Made me realize that it is not really clear what I am asking for. Thus I will try to clarify:
I want to write a base class that other will have to derive from. Constructing the derived objects involves quite specific stuff that I would like to keep out of the base class. When searching the web for virtual constructor I found the above mentioned q&a and I think a factory approach could work well. However, I am not sure how to achieve the following:
I Don't get your question exactly but, you might looking for this.
#include <iostream>
#include <conio.h>
class Base
{
virtual void afterConstruction() = 0;
};
class Derived : Base {
private:
Derived() : Base() {}
public:
void afterConstruction(){ std::cout << "construct" << std::endl; }
protected:
static Derived GetInstance()
{
return Derived();
}
};
template <class T> class MyFactory : T
{
public:
static T GetInstance()
{
// Make sure every kind of T has protected GetInstance()
T t = T::GetInstance();
T* p = &t;
p->afterConstruction();
return t;
}
};
int main(int argc, char** argv) {
Derived d = MyFactory<Derived>::GetInstance();
// Derived d1; // will cause error
_getch();
return 0;
}
Edited Answer
#include <iostream>
#include <conio.h>
class Base
{
protected:
Base() { }
virtual void afterConstruction() = 0;
virtual Base* GetInstance() = 0;
};
class Derived : public Base {
protected:
Derived() : Base() { }
void afterConstruction()
{
static bool bConstrucred = false;
if (!bConstrucred)
{
std::cout << "construct" << std::endl;
bConstrucred = true;
}
}
Derived* GetInstance()
{
afterConstruction();
return this;
}
};
template <class T> class MyFactory : public T
{
public:
T* GetInstance() { return T::GetInstance(); }
};
int main(int argc, char** argv) {
Derived* d = MyFactory<Derived>().GetInstance();
// Derived d1; // will cause error
_getch();
return 0;
}