从基类的shared_ptr获取对象

时间:2019-04-22 22:54:07

标签: c++ smart-pointers

我可以在C ++中通过smart_ptr实现常规多态吗?

我有以下两个结构:

struct Base{... // methods and variables
};

struct D: Base{... // inherited methods and variable plus a few new methods
};

这两个结构将像这样使用:

typedef msm::back::state_machine<Base>  ESM; //(Base_namespace::ESM)
typedef msm::back::state_machine<D>  ESM; //(Derived_namespace::ESM)
//The state_machine is from boost lib.
//They (ESM and ESM) are in different namespaces, so no problem using them

在另外两个班级中,我有这个:

Derived_namespace{
class derived_sth: public Base_namespace::sth
{
    public:
    //This method is used to assgin the m_base a share_ptr of type base ESM
    void setPtr(const std::shared_ptr<Derived_namespace::ESM> sm){
        m_base = std::dynamic_pointer_cast<Base_namespace::ESM>(sm);
    }
};
}

Base_namespace{
class sth
{
    public:
    void Base_namespace::onStart()
    {
        //!!!!!!!!
        //Here comes the problem, the variable sm turns out 
        //to be null, or some value that causes the following
        //if() statement to be false;
        //So how can I get the correct result?
        //!!!!!!!!
        std::shared_ptr<Base_namespace::ESM> sm = m_base.lock();
        if (sm)
        {
            sm->start();
        }
    }
    protected:
        std::weak_ptr<Base_namespace::ESM>  m_base;
    ...
};
}

方法setPtr()的类型为std::shared_ptr<Derived_namespace::ESM>,然后为onStart()。因此,m_base被调用时onStart()不应为空。

具体问题在评论中。感谢您的帮助,我也想了解有关使用智能指针进行多态性的一般良好做法。谢谢!

1 个答案:

答案 0 :(得分:-1)

具有智能指针的多态与具有常规指针的多态的工作方式相同。

例如,假设我有一个带有虚拟Animal方法的类speak()

class Animal {
   public:
    virtual ~Animal() = default;
    virtual void speak() {
        std::cout << "I am an animal.\n"; 
    }
};

我可以对狗,猫和牛重写此方法:

class Dog : Animal {
   public: 
    void speak() override {
        std::cout << "Woof.\n";
    }
};

class Cat : Animal {
   public:
    void speak() override {
        std::cout << "Meow.\n";
    }
};

class Cow : Animal {
   public:
    void speak() override {
        std::cout << "Moo.\n";
    }
};

现在有了这个,我可以编写一个使动物说话两次的函数:

void speakTwice(Animal& animal) {
    animal.speak();
    animal.speak();
}

由于speak是虚拟的,因此将调用speak的正确版本:

Dog dog;
Cat cat;
Cow cow; 
// Prints:
// > Woof.
// > Woof.
speakTwice(dog); 
// Prints:
// > Meow.
// > Meow.             
speakTwice(cat);
// Prints:
// > Moo.
// > Moo.
speakTwice(cow); 

仅适用于 speak是虚拟的。除了使用->

之外,它与智能指针的工作方式相同。
void speakTwice(std::shared_ptr<Animal> animal) {
    animal->speak();
    animal->speak();
}

weak_ptr配合使用:

这也是非常简单的方法,下面的示例将告诉您指针是否为空或过期。

void speakTwice(std::weak_ptr<Animal> const& animal) {
    if(animal.expired()) {
        std::cerr << "Animal was expired.\n";
        return;
    }
    auto ptr = animal.lock();
    if(ptr) {
        ptr->speak();
        ptr->speak();
    } else {
        std::cerr << "Animal was null.\n"; 
    }
}
}

为什么您的代码遇到问题

尽管有一些可能,您没有提供足够的代码来帮助我们解决问题:

  • 您没有为m_base分配任何内容,因此锁定时为空
  • 也许您忘记了start()虚拟化? IDK
  • 我们真的没有足够的信息来解决问题

是的