C++ 克隆抽象基类(不干预派生类)

C++ 克隆抽象基类(不干预派生类),c++,copy,abstract-class,clone,C++,Copy,Abstract Class,Clone,我正在经历一个具有挑战性的问题,这是无法解决的——希望直到现在。我正在开发我自己的框架,因此,我试图为用户提供灵活性,让所有的代码都变得复杂 首先,我有一个用户可以实现的抽象基类,显然是简化的: class IStateTransit { public: bool ConnectionPossible(void) = 0; } // A user defines their own class like so class MyStateTransit : public IStateTr

我正在经历一个具有挑战性的问题,这是无法解决的——希望直到现在。我正在开发我自己的框架,因此,我试图为用户提供灵活性,让所有的代码都变得复杂

首先,我有一个用户可以实现的抽象基类,显然是简化的:

class IStateTransit
{
public:
    bool ConnectionPossible(void) = 0;
}

// A user defines their own class like so
class MyStateTransit : public IStateTransit
{
public:
    bool ConnectionPossible(void){ return true; }
}
接下来,我定义一个工厂类。用户可以注册他们自己的自定义状态传输对象,并在以后使用他们选择的字符串标识符引用它们:

class TransitFactory : public Singleton<TransitFactory>
{
public:
    template<typename T> void RegisterStateTransit(const string& name)
    {
        // If the transit type is not already registered, add it.
        if(transits.find(name) == transits.end())
        {
            transits.insert(pair<string, IStateTransit*>(name, new T()));
        };
    }

    IStateTransit* TransitFactory::GetStateTransit(const string& type) const
    {
        return transits.find(type)->second;
    };

private:
    map<string, IStateTransit*> transits;
}
现在的问题可能很明显,每当用户通过调用GetStateTransite请求传输时,系统当前都会返回相同的对象—指向当前所访问的相同对象的指针。我想改变这个

问题:如何返回原始IStateTransit对象的新克隆,而无需用户定义自己的复制构造函数或构造函数。理想情况下,我希望GetStateTransit方法能够将IStateTransit对象强制转换为它在运行时的派生类型,并返回该实例的克隆。最大的障碍是,我不希望用户必须实现任何额外的、可能很复杂的方法


4个小时的谷歌搜索和尝试让我一事无成。有答案的人是英雄

对我来说,这个问题听起来可能有帮助。使用此模式,库客户端可以定义框架如何构建其类型。客户机可以将自己的工厂子类注入到框架中,并在那里定义应该构建的类型

你需要的是额外的 工厂的基类 作为客户:衍生混凝土工厂 将工厂的子类型作为客户端注入框架的一种方法 调用工厂方法来创建新类型


这对您有帮助吗?

问题是您没有执行克隆的类型信息,因为您只有一个指向基类类型的指针,而不知道实现了哪些派生类型以及哪些派生类型可用

我认为谷歌4个小时的搜索没有找到任何结果是有原因的。如果您希望IStateTransit是可克隆的,那么必须有一个接口,派生类实现者在该接口中提供某种克隆方法实现

如果这不是你想听的,我很抱歉

然而,实现克隆方法不应该是一个很大的负担。只有类实现者知道如何复制类,如果提供了正确的复制构造函数,则可以为叶节点类实现克隆,如下所示:

Base* clone() const
{
    return new MyType(*this);
}

你甚至可以宏观化它;尽管我不会。

如果我正确理解了这个问题,您不应该在地图中插入新的t-s,而应该是创建新t-s的对象

struct ICreateTransit
{
    virtual ~ICreateTransit() {}
    virtual IStateTransite* create() const = 0;

};

template <class T>
struct CreateTransit: public ICreateTransit
{
    virtual IStateTransit* create() const { return new T(); }
};
如果默认的stateTransition不允许,那么修改stateTransition使其保存一个要复制的t应该是不可能的


我认为这类技术的通用名称称为类型擦除派生类型记住特定类型,尽管基类不知道这些类型。

好吧,我已经研究过了。问题是,就像Charles Bailey发布的克隆情况一样,用户仍然必须实现自己版本的方法。似乎不可避免。我想你是对的。我想我会在基类中添加一个额外的纯虚拟克隆方法。啊,我还是希望有更干净的安排方式。或者一些肮脏的解决方法,比如存储IStateTransit注册期间使用的类型,以某种方式将其转换为字符串,然后使用该字符串进行类型转换。。。谢谢你的努力。@Waldo Spek:从根本上说,你甚至不知道可能有什么派生类,所以在设计/实现派生类之前,你不可能生成正确的类复制代码。您不必将克隆函数设置为虚拟方法,您可以将执行克隆的用户提供的函数指针与指向类的指针一起存储,但我认为它不会以任何方式变得更整洁。@Waldo:您似乎不理解静态类型。类型在编译时确定,强制转换的目标也是如此。字符串永远不能用作类型。在某些时候,您必须委托给一个知道静态类型以及如何复制它的函数。克隆方法可以做到这一点。我忽略的是我的IStateTransit类包含一些属性。假设它包含一个布尔值。我只希望我的新克隆/副本包含该布尔值。现在,我想说,既然我正在创建一个用户定义的派生类的新实例,至少我有一些类型信息。因为我只关心将抽象基类中的信息复制到克隆中,所以我认为可能有一种方法。不过,我很清楚我在碰运气。我实际上只想复制构建我的基础class@GMan:是的,我理解这个概念。但是我的心在颤抖
indof拒绝相信我会坚持这样的解释,因为我的派生类的实例是在运行时通过使用模板函数创建的。我只希望我能捕捉到用户告诉程序的信息,即:factory->RegisterStateTransitlinear。。。捕捉线性状态。但是,再一次:我意识到我在碰运气。顺便说一句:你的基类成员,比如IStateTransit::Connection,可能需要是虚拟的。另外,您应该提供一个虚拟析构函数,它不能做任何事情,这样就可以很好地定义通过基指针删除派生实例。@Evan:你说得对,我说得对。我输入的代码没有复制,忘记了…嘿,哇,从这里判断,这实际上可能是解决方案!我的手指很痒,但我明天会尝试实施,然后再给你回复。现在需要好好睡一觉:
transits.insert(pair<string, ICreateTransit*>(name, new CreateTransit<T>()));
return transits.find(type)->second->create(); //hopefully with error handling