【问题标题】:shared_ptr with multiple interfacesshared_ptr 具有多个接口
【发布时间】:2017-02-18 23:23:11
【问题描述】:

考虑以下类:

class MyInterface1 {
    ...
};
class MyInterface2 {
    ...
};
class MyClass : public MyInterface1, public MyInterface2 {
    ...
};

如果我有以下代码:

void MyFunction(shared_ptr<MyInterface1>& out); // returns a make_shared<MyClass>

shared_ptr<MyInterface1> c1;
shared_ptr<MyInterface2> c2;
MyFunction(c1);
c2 = c1;

我无法将 c2 分配给 c1。

此外,如果我只调用MyFunction(c2),它也不会编译,因为 MyClass 是从 MyInterface1 和 MyInterface2 派生的,所以我希望它可以工作。这似乎是一个值得分享的编译器错误(Visual Studio 2015 Update 3)。谁能重现这个?

【问题讨论】:

  • 不,这不是编译器错误。
  • 这与shared_ptr无关,这也不适用于原始指针。
  • MyClass 可以是MyInterface1MyInterface2,但MyInterface1 和`MyInterface2 之间没有关系。
  • 仅仅因为你碰巧有一个MyClass 结合了MyInterface1MyInterface2 并不意味着MyInterface1 的所有可能派生都具有相似的相关性。为什么编译器要做出这样的假设?

标签: c++ c++11 shared-ptr


【解决方案1】:

MyInterface1MyInterface2 是完全不相关的类型。仅仅因为c1 指向的对象具有从两者继承的运行时类型,静态类型是不兼容的,您将不得不使用强制转换将一个分配给另一个

shared_ptr<MyInterface1> c1;
shared_ptr<MyInterface2> c2;
MyFunction(c1);
c2 = dynamic_pointer_cast<MyInterface2>(c1);

Live Example

当然,这只有在*c1 的实际动态类型继承自MyInterface2 时才有效。与任何 dynamic_cast 一样,如果类型不兼容,dynamic_pointer_cast 将返回 nullptr

【讨论】:

    【解决方案2】:

    您可以使用原始指针执行此操作,但无法使用 shared_ptr 执行此操作。不要使用 shared_ptr,而是这样做:

    void MyFunction(MyInterface1* out); // returns a new MyClass()
    
    MyInterface1* c1;
    MyInterface2* c2;
    MyFunction(c1);
    c2 = (MyInterface2*)c1;
    MyFunction((MyInterface1*)c2);
    

    它肯定更清洁、更容易且更易于维护。由于您不再使用 shared_ptr 并且开销更少,因此它也更快。如果您关心性能,请不要使用 shared_ptr。

    【讨论】:

    • 由于多种原因不是最佳选择。避免 C 风格的强制转换——它会伤害你。在大多数情况下,通过带有没有明确所有权的指针的参数返回一个新对象是另一个坏主意。
    • 非常糟糕的建议,伙计。 C 风格的演员就像上帝在说:“相信我。我知道我在做什么。”最好希望上帝是对的,因为它会发生对或错。在这种情况下,你是在扮演上帝,你错了。
    • 我是唯一真正提供解决方案的人,其他人都说这是个坏主意。如果这是一个坏主意,请与语言的创建者一起讨论。这不是关于风格的问题,所以把你的“圣战”带到别处......开发人员提出了一个问题,而我是唯一一个真正给出答案的人,而其他人只是让 cmets 抱怨并且没有有价值的见解......不想知道人们对社区有意见。
    • 如何未定义?它派生自这两个基类。
    • c2 = (MyInterface2*)c1;之后c2所指的地址不一定与c1的相同。不,我在这里错了。没有任何关系可以使这种情况发生在这里。我很抱歉。它只是违反了严格的别名。
    猜你喜欢
    • 2015-12-14
    • 2011-05-24
    • 2017-10-29
    • 2017-02-15
    • 1970-01-01
    • 2019-10-12
    • 1970-01-01
    • 2016-01-27
    • 2014-10-06
    相关资源
    最近更新 更多