unique_ptr和多态

use*_*427 14 c++ smart-pointers c++11

我有一些目前使用原始指针的代码,我想改为智能指针.这有助于以各种方式清理代码.无论如何,我有返回对象的工厂方法,以及调用者管理它们的责任.所有权不是共享的,所以我unique_ptr认为这是合适的.我返回的对象通常都来自一个基类Object.

例如,

class Object { ... };
class Number : public Object { ... };
class String : public Object { ... };

std::unique_ptr<Number> State::NewNumber(double value)
    {
        return std::unique_ptr<Number>(new Number(this, value));
    }

std::unique_ptr<String> State::NewString(const char* value)
    {
        return std::unique_ptr<String>(new String(this, value));
    }
Run Code Online (Sandbox Code Playgroud)

经常返回的对象需要传递给另一个函数,该函数对类型的对象Object(基类)进行操作.没有任何智能指针,代码就是这样.

void Push(const Object* object) { ... } // push simply pushes the value contained by object onto a stack, which makes a copy of the value
Number* number = NewNumber(5);
Push(number);
Run Code Online (Sandbox Code Playgroud)

将此代码转换为使用时,unique_ptrs我遇到了多态问题.起初,我决定简单地改变定义Push使用unique_ptrs过,但是这会产生尝试使用派生类型时,编译错误.我可以将对象分配为基类型,比如

std::unique_ptr<Object> number = NewNumber(5);
Run Code Online (Sandbox Code Playgroud)

并传递给那些Push当然有效的.但是我经常需要在派生类型上调用方法.最后我决定对Push指向存储的对象的指针进行操作unique_ptr.

void Push(const Object* object) { ... }
std::unique_ptr<Object> number = NewNumber(5);
Push(number.get());
Run Code Online (Sandbox Code Playgroud)

现在,发布的原因.我想知道这是否是解决问题的正常方法?Push操作unique_ptrvs对象本身更好吗?如果是这样,如何解决多态问题?我认为简单地投射ptrs是行不通的.是否需要从智能指针获取底层指针?

谢谢,对不起,如果问题不明确(请告诉我).

编辑:我认为我的Push功能有点含糊不清.它创建了基础值的副本,并不实际修改或存储输入对象.

Pup*_*ppy 11

最初我决定简单地将Push的定义更改为使用unique_ptrs,但是在尝试使用派生类型时会产生编译错误.

您可能没有正确处理唯一性.

void push(std::unique_ptr<int>);
int main() {
    std::unique_ptr<int> i;
    push(i); // Illegal: tries to copy i.
}
Run Code Online (Sandbox Code Playgroud)

如果这个被编译,它将简单地打破不变量unique_ptr,只有一个unique_ptr拥有一个对象,因为两者i和本地参数push都拥有它int,所以它是非法的.unique_ptr只是移动,它不可复制.它与派生到基本转换无关,它可以unique_ptr完全正确地处理.

如果push拥有该对象,则使用std::move将其移动到那里.如果没有,则使用原始指针或引用,因为这是您用于非拥有别名的内容.

  • @ user1520427:对指针的引用是防止多态的因素,因为uniqe_ptr特化是不相关的类型.您必须使用对象本身的引用. (4认同)
  • @ user1520427:不,这样做很好.但是你的解决方案需要将`unique_ptr <Number>`复制到`unique_ptr <Object>`然后引用它 - 这涉及复制它. (2认同)