3

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

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

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

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

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

  • 应该只能从工厂创建 Derived 的实例。否则,可以在不一致的状态下创建派生对象。(我想仅在基类中我无法强制执行此操作,但要求 Derived 的每个编码器将构造函数设为私有/受保护就足够了。)
  • 如果可能,Derived 应该只实现 Base 的纯虚拟方法,因为这样编写 Derived 就非常舒服(IDE/编译器将准确地告诉您必须实现什么,而不是在例如模板接口时出现冗长且有时神秘的错误消息参数必须实现)
4

1 回答 1

1

我不完全明白你的问题,但是,你可能会寻找这个。

#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;
}
于 2015-04-02T09:37:46.737 回答