C++协方差返回类型有哪些缺点?

Sca*_*cab 0 c++ covariance

我最近不得不处理C++ 协方差返回类型,例如以下构造:

struct Base
{
     virtual ~Base();
};
struct Derived : public Base {};

struct AbstractFactory
{
    virtual Base *create() = 0;
    virtual ~AbstractFactory();
};

struct ConcreteFactory : public AbstractFactory
{
    virtual Derived *create()
    {
        return new Derived;
    }
};
Run Code Online (Sandbox Code Playgroud)

它允许客户端代码在需要时将Derived对象视为Base类型或Derived类型,特别是不使用dynamic_caststatic_cast.

这种方法的缺点是什么?这是糟糕设计的标志吗?

谢谢.

Mic*_*ler 5

协方差不适用于智能指针,因此协方差违反:

切勿通过 C++核心指南的原始指针(T*)或引用(T&)转移所有权 .有一些技巧可以限制问题,但协变值仍然是一个原始指针.

该文件的一个例子:

X* compute(args)    // don't
{
    X* res = new X{};
    // ...
    return res;
}
Run Code Online (Sandbox Code Playgroud)

这与问题中的代码几乎相同:

virtual Derived *create()
{
    return new Derived;
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,以下内容对于以下内容都是非法shared_ptrunique_ptr:

struct AbstractFactory
{
    virtual std::shared_ptr<Base> create() = 0;
};

struct ConcreteFactory : public AbstractFactory
{
    /*
      <source>:16:38: error: invalid covariant return type for 'virtual std::shared_ptr<Derived> ConcreteFactory::create()'
    */
    virtual std::shared_ptr<Derived> create()
    {
        return std::make_shared<Derived>();
    }
};
Run Code Online (Sandbox Code Playgroud)

编辑

nm的答案显示了一种模拟语言协方差的技术,以及一些额外的代码.它有一些潜在的维护成本,因此在决定走哪条路之前要考虑到这一点.