使用shared_ptr和多重继承类

8

我有一个继承了两个接口的类:

class Multi : public IFoo, public IBar {
public:
  virtual ~Multi();

  // Foo part
  virtual void fooMethod();
  // ...

  // Bar part
  virtual void barMethod();
  // ...
};

很不幸,这个类不能被分解成每个接口的两个独立类。实际上,在类的实现中,这些实体(Foo和Bar)是紧密耦合的,但在未来它们可能会变成独立的。

另一个类想要使用Multi类,拥有指向IFoo和IBar的指针:

class ClientClass {
    public:
       ClientClass(); // constructor
       // smth
    private:
       std::shared_ptr<IFoo> foo_;
       std::shared_ptr<IBar> bar_;
};

在构造函数中我会做类似以下的事情:

ClientClass::ClientClass(){
    auto pMulti = new Multi;
    foo_ = std::shared_ptr<IFoo>(pMulti);
    bar_= std::shared_ptr<IBar>(pMulti);  
}

但是每个共享指针都有单独的引用计数器,这会导致在类销毁时删除已经被删除的指针,我说的对吗?

  1. 我应该如何处理它?
  2. 在这种情况下,最佳实践是什么?

看起来你现在应该将IFoo和IBar分开。 :) - Jerry YY Rain
@Jerry 我无法将它们分开,因为它们有共同的初始化、释放等操作,我不能改变这一点。 - vard
2个回答

9
ClientClass::ClientClass()
{
    auto pMulti = std::make_shared<Multi>();
    foo_ = pMulti;
    bar_ = pMulti;  
}

确保它们具有相同的引用计数器。您可以自己看到:

#include <iostream>
#include <memory>

class Base1{};
class Base2{};
class Derived : public Base1, public Base2 {};

int main()
{
    auto derived = std::make_shared<Derived>();
    std::shared_ptr<Base1> base1 = derived;
    std::shared_ptr<Base2> base2 = derived;

    std::cout << "base1 usecount = " << base1.use_count() << '\n';
    std::cout << "base2 usecount = " << base2.use_count() << '\n';
    std::cout << "derived usecount = " << derived.use_count() << '\n';

    return 0;
}

生成:

base1 usecount = 3
base2 usecount = 3
derived usecount = 3

你确定shared_ptr的赋值运算符允许使用不同的模板类型作为参数吗?shared_ptr<IFoo> = shared_ptr<Multi>? - vard
@vard 是的,只要右侧的类型是从左侧继承而来的。 - Martin Drozdik

0

我不确定你想用这些指针做什么,但另一种解决方案可能是存储一个 std::unique_ptr<multi> multi_; 并拥有一些接口函数将其静态转换为普通指针或引用:

IFoo& ClientClass::get_ifoo() {
  return *(static_cast<IFoo*>(multi_.get())); 
}

IBar& ClientClass::get_ibar() {
  return *(static_cast<IBar*>(multi_.get())); 
}

只要你不从类中传递它们,并且不对它们调用delete[],那么它应该是相当安全的。

这里真的需要强制转换吗?(即这些函数没有意义。) - juanchopanza
@juanchopanza 仔细一看我也明白了,但是共享指针的理念不也应该是这样吗? - DarioP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接