我不确定问题标题是否准确......让我先解释一下我原来的简单场景,然后继续解释我想做什么,但不能。
最初,我有类似的东西:
class Operand;
Operand genOperandA() { ...; return Operand(); }
Operand genOperandB() { ...; return Operand(); }
... // more operand-generation functions
typedef Operand (*OpGen)();
// Table of function pointers
static const OpGen generators[] =
{
genOperandA,
genOperandB,
...
};
// Function to do some operation on the operand
void operate(Operand& op);
...
// Example call
operate(generators[1]());
到目前为止一切顺利(我认为)。但是,现在有几种派生的操作数类型,例如 class RegisterOperand : public Operand
。我有新的,专注的 genOperand
理想情况下将返回派生类型的实例的函数。但我不能这样做:
Operand genOperandC() { ...; return RegisterOperand(); }
我不能这样做:
RegisterOperand genOperandC() { ...; return RegisterOperand(); }
static const OpGen generators[] =
{
...
genOperandC,
};
但是,我知道如果我要返回引用或指针类型,这将有效,所以我目前唯一的选择是:
Operand *genOperandC() { ...; return new RegisterOperand(); }
现在需要明确的清理,这是原本不必要的。
我还没考虑过任何替代方案?
可能有其他设计不要求您使用指针,但如果您需要或想要这样做,这可能会让您感兴趣。
如果返回一个指针是一个问题(因为需要“清理”东西),你绝对应该考虑使用智能指针作为返回类型。
以下是使用智能指针的工厂方法的示例:
boost::shared_ptr<Operand> genOperandC()
{
return boost::shared_ptr<Operand>(new RegisterOperand());
}
这样,您就不必打电话了 delete
手动:它将由析构函数完成 boost::shared_ptr<Operand>
在需要时为你服务。
如果之后你需要施放结果指针, boost
提供了铸造功能:
boost::shared_ptr<Operand> op = genOperandC();
boost::shared_ptr<RegisterOperand> rop =
boost::dynamic_pointer_cast<RegisterOperand>(op);
可能有其他设计不要求您使用指针,但如果您需要或想要这样做,这可能会让您感兴趣。
如果返回一个指针是一个问题(因为需要“清理”东西),你绝对应该考虑使用智能指针作为返回类型。
以下是使用智能指针的工厂方法的示例:
boost::shared_ptr<Operand> genOperandC()
{
return boost::shared_ptr<Operand>(new RegisterOperand());
}
这样,您就不必打电话了 delete
手动:它将由析构函数完成 boost::shared_ptr<Operand>
在需要时为你服务。
如果之后你需要施放结果指针, boost
提供了铸造功能:
boost::shared_ptr<Operand> op = genOperandC();
boost::shared_ptr<RegisterOperand> rop =
boost::dynamic_pointer_cast<RegisterOperand>(op);
你可以包装:
class Operand
{
public:
private:
std::unique_ptr<OperandImpl> mImpl;
};
这与策略模式类似:实际的操作数行为是隐藏的,可通过非虚拟接口访问。用户获得一份副本 Operand
,她不需要了解它的内部信息,也可以使用它,你可以自由地实现各种派生行为。
这样的事怎么样?
请注意,您不能简单地操作(generators [i]()),因为原始操作()采用非const引用。
#include <iostream>
#include <string>
#include <memory>
class Operand {
public:
Operand(std::string x = "Operand"): x(x) {}
const std::string x;
};
class RegisterOperand: public Operand {
public:
RegisterOperand(std::string x = "RegisterOperand")
: Operand(x) {}
};
typedef std::auto_ptr<Operand> POperand;
POperand genOperandA() { return POperand(new Operand("genOperandA")); }
POperand genOperandB() { return POperand(new Operand("genOperandB")); }
POperand genOperandC() { return POperand(new RegisterOperand()); }
// more operand-generation functions
typedef POperand (*OpGen)();
// Table of function pointers
static const OpGen generators[] =
{
genOperandA,
genOperandB,
genOperandC,
};
void operate(const POperand& op)
{
std::cout << op->x << std::endl;
}
int main()
{
operate(generators[0]());
operate(generators[1]());
operate(generators[2]());
return 0;
}
我知道这个问题是前一段时间被问过的,但我最近自己遇到了这个问题,我提出了一个不同的解决方案,我在这里可能会有所帮助。
因此,我们的想法是创建一个包装器来管理指针,但也支持复制包装器,而不像只能移动的唯一指针。
class PolymorphicType {
public:
/*
Class interface ...
*/
PolymorphicType() { it = nullptr; }
virtual ~PolymorphicType() { if(it != nullptr) delete it; }
PolymorphicType& operator=(const PolymorphicType& org) {
//Clone the derived type and store it
if(org.it != nullptr)
it = org.it->clone();
}
private:
Base* it;
};
每个派生类现在必须实现它自己的克隆方法,你很高兴!
以防这里有一篇很好的文章解释了派生类型的克隆是如何工作的: 仅使用基类指针复制派生实体(没有详尽的测试!) - C ++
希望这可以帮助别人!