使用工厂时如何 "hide" 构造函数?

How to "hide" constructor when using a factory?

我遇到了一种情况,我想从构造函数中调用虚方法。这当然是不可能的(或者至少它不会产生所需的行为)。 In this answer 作为变通方法,建议使用工厂方法。我写了这样的东西:

#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;
}

这是一种模板方法模式。每个派生 class 都可以自定义其构建方式。但是,只有当此 classes 的用户无法直接调用构造函数或 afterConstruction() 时,整个构造才有意义。因此,我想将它们都设为私有。也许这是一个愚蠢的问题,我只是没有看到明显的问题。也许我可以通过使用友谊或类似的东西来实现这一点,但我不确定这是否是最好的方法。隐藏这两个方法并只允许通过工厂方法创建对象的好方法是什么?

编辑: Ka7Im1011 让我意识到我的要求并不是很清楚。因此,我将尝试澄清:

我想写一个基础 class 其他人必须从中派生。构建派生对象涉及非常具体的内容,我想将其排除在基础 class 之外。在网上搜索虚拟构造函数时,我发现了上面提到的问答,我认为工厂方法可以很好地工作。但是,我不确定如何实现以下目标:

我不太明白你的问题,但你可能正在寻找这个。

#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;
}

已编辑答案

#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;
}