新的共享指针和虚拟函数

new, shared pointer & virtual functions

本文关键字:虚拟 函数 指针 共享      更新时间:2023-10-16

在我的程序中,我面临着另一个困难(我将它们全部存储起来,并在一个burts中提出许多问题:p)。我所拥有的是一个函子——这些函子都是从DuplicateFn继承的——它有一个虚运算符(),并且每个子函数都应该写出它自己的版本。

现在,其中一个子线程(称为merge)可能不会成功,在这种情况下,它应该尝试一个回退方法。当前这个类看起来像:

class MergeFn : public DuplicateFn {
public:
    MergeFn() : FallBack(new SkipFn())
    {
    }
    MergeFn(GMProject const* Out, GMProject const* In, DuplicateFn* f) 
        : DuplicateFn(Out, In), FallBack(f)
    {
    }
    virtual void operator() (GMProject::pTree& tOut, const GMProject::pTree& tIn) const {
        if (!GMProject::isMergeable(tOut.GetName())) {
            (*FallBack)(tOut, tIn); //virtual table resolves this to the correct class
        } else {
        }
    }
private:
    std::shared_ptr<DuplicateFn> FallBack;
};

我认为问题在这里已经很明显了——在非默认构造函数中,这个方法获取给定参数的所有权。-这不是我想要的:它应该复制该参数并保留其所有权。
现在我尝试了, FallBack(new DuplicateFn(f)),但是这也不起作用-因为现在有一个编译错误,它试图用纯虚拟方法从类实例化对象。

我该怎么做呢?我必须为每个类型指定一个特定的构造函数吗?-只是为了正确地复制它?还是我必须通过RTTI?我希望有比这两个更好的方法。

编辑要显示如何初始化(和使用)mergeFn:

std::unique_ptr<detail::DuplicateFn> foo;
foo.reset(new detail::MergeFn(this, &Other, DuplicateFns.at(HandleDuplicate)));

DuplicateFns是一个映射,它帮助将用户输入(字符串)转换为函数指针。-或者像现在一样,指向DuplicateFn子类型对象的指针(指针类型为DuplicateFn*)

然后用作回调方法

ProjectTree.combine_if(tree, &SimilarTreeValue, foo.get());

将两棵树合并为一棵-当SimilarTreeValue返回true时,该条目被认为是重复的。如果条目是叶子,则调用第三个形参——我们正在讨论的函子:)。

最简单的解决方案(在我看来)是改变构造函数的签名,要求已经有一个共享指针:

MergeFn(GMProject const * Out,
        GMProject const * In,
        std::shared_ptr<DuplicateFn> f) /* ... */

第二个选择是用clone()函数赋予你的整个类层次结构:

struct Base
{
  virtual Base * clone() const { return new Base(*this); }
};
struct Der1 : Base
{
  virtual Der1 * clone() const { return new Der1(*this); }
};

可以初始化FallBack(f->clone())

我个人会选择第一个版本,我也会检查用唯一指针替换共享指针是否可行。

new DuplicateFn(f)

只对函子f进行切片。

你需要一个克隆函数:

#include <typeinfo>
#include <cassert>
template <class T>
// runtime checked clone function
// T::do_clone() must be accessible to checked_clone
T *checked_clone (const T* that) {
    T *p = that->do_clone();
    assert (typeid (*p) == typeid (*that));
    return p;
}
// clone for an abstract class
#define IMPLEMENT_CLONE_ABSTRACT(Class) 
    friend Class *checked_clone<Class> (const Class* that); 
 
public: 
    Class *clone_naked() const { 
        return checked_clone (this); 
    } 
    unique_ptr<Class> clone_unique() const { 
        return unique_ptr<Class> (checked_clone (this)); 
    }      
private: 
    virtual Class *do_clone() const = 0; 
/* end of IMPLEMENT_CLONE_ABSTRACT */
class Base {
    IMPLEMENT_CLONE_ABSTRACT(Base)
};
// clone for a concrete class
#define IMPLEMENT_CLONE_CONCRETE(Class) 
    friend Class *checked_clone<Class> (const Class* that); 
 
public: 
    Class *clone_naked() const { 
        return checked_clone (this); 
    } 
    unique_ptr<Class> clone_unique() const { 
        return unique_ptr<Class> (checked_clone (this)); 
    }      
 
private: 
    virtual Class *do_clone() const {  
        return new Class (*this); 
    } 
/* end of IMPLEMENT_CLONE_CONCRETE */
class Derived : public Base {
    IMPLEMENT_CLONE_CONCRETE(Derived)
};

您可以使用shared_ptr的构造函数,该构造函数接受自定义析构函数并为其传递空函数。例如。

void dontDelete(DuplicateFn *pFn ) {
  // Do nothing!
  }
class MergeFn : public DuplicateFn { 
public: 
    MergeFn() : FallBack(new SkipFn()) 
    { 
    }
    MergeFn(GMProject const* Out, GMProject const* In, DuplicateFn* f)  
        : DuplicateFn(Out, In), FallBack(f, dontDelete) 
    { 
    }
    virtual void operator() (GMProject::pTree& tOut, const GMProject::pTree& tIn) const { 
        if (!GMProject::isMergeable(tOut.GetName())) { 
            (*FallBack)(tOut, tIn); //virtual table resolves this to the correct class 
        } else { 
        } 
    }
private: 
    std::shared_ptr<DuplicateFn> FallBack; 
};