vard
vard

Reputation: 2302

Using shared_ptr with multi inheritance class

I have an class which inherit two interfaces:

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

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

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

Unfortunately this class cannot be decomposed in two separate classes for each interface. In fact in class implementation those entities (Foo and Bar) are tightly coupled, but in future they could become separate.

Another one class wants to use Multi class, having a pointer to IFoo and IBar:

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

In constructor I do something like:

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

But each of those shared pointers has separate reference counter, and it leads to deleting already deleted pointer on class destruction, am I right?

  1. How should I treat it?
  2. What is best practics for such case?

Upvotes: 9

Views: 4779

Answers (2)

DarioP
DarioP

Reputation: 5465

I don't know exactly what you want to do with those pointers, but an alternative solution may be to store a std::unique_ptr<multi> multi_; and have a couple of interface functions that static cast it to plain pointers or to references:

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

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

As long as you don't pass those out from the class, and don't call delete[] on them it should be quite safe.

Upvotes: 0

Martin Drozdik
Martin Drozdik

Reputation: 13343

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

would ensure that they have the same reference counter. You can see it for yourself:

#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;
}

produces:

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

Upvotes: 9

Related Questions