将共享指针的派生类切换到基类

Switch Derived class of a shared pointer to base class

本文关键字:基类 派生 共享 指针      更新时间:2023-10-16

我目前正在尝试将存储在共享指针中的派生类的类型切换到基类。问题是Derived类继承自基类,并且模板化如下:

基本类别:

#define PRINT(s) std::cout << s << std::endl
class Base {
public:
    Base() : m_a(1) {}
    virtual ~Base() = default;
    virtual void print() { PRINT("BASE"); }
    int m_a;
};

派生类依赖于枚举模板:

enum eType { e0, e1 };
template<eType et>
class Derived : public Base { };
template<>
class Derived<e0> : public Base {
public:
    Derived() { this->m_a = e0; }
    void print() { PRINT("Derived e0, m_a value: " << e0 ); }
};
template<>
class Derived<e1> : public Base {
public:
    Derived() { this->m_a = e1; }
    void print() { PRINT("Derived e1, m_a value: " << e1 ); }
};

我的目标是有一个指向基类的共享指针,这样就可以从以下两个派生类切换:

int main()
{
    std::shared_ptr<Base> sp_00 = std::make_shared<Derived<e0>> ();
    std::shared_ptr<Base> sp_01 = sp_00;
    sp_01->print();
    std::shared_ptr<Base> sp_10 = std::make_shared<Derived<e1>> ();
    *sp_01 = *sp_10;
    sp_01->print();
    sp_10->print();
}

*sp_01 = *sp_10;行一样,唯一的问题是基类的指针从派生类型Derived<e0>切换到派生类型Derived<e1>。然而,在我的示例中,我得到了行sp_01->print();和行sp_10->print();的不同结果,指示sp_01保持为Derived<e0>类型。

我想避免sp_01 = sp_10;,因为它会改变指针。在上面的例子中,它将导致sp_00 != sp_01,并且我希望sp_00sp_01共享同一个对象。

我尝试用非模板派生类替换模板派生类,如下所示:

class Derived_e0 : public Base {
public:
    Derived() { this->m_a = e0; }
    void print() { PRINT("Derived e0, m_a value: " << e0 ); }
};
class Derived_e1 : public Base {
public:
    Derived() { this->m_a = e1; }
    void print() { PRINT("Derived e1, m_a value: " << e1 ); }
};

下面的代码给出了与使用模板的代码相同的结果。

int main()
{
    std::shared_ptr<Base> sp_00 = std::make_shared<Derived_e0> ();
    std::shared_ptr<Base> sp_01 = sp_00;
    sp_01->print();
    std::shared_ptr<Base> sp_10 = std::make_shared<Derived_e1> ();
    *sp_01 = *sp_10;
    sp_01->print();
    sp_10->print();
}

所以我的问题是,如何在不改变shared_ptr本身的情况下切换由共享指针指向的派生对象(该对象在程序的其他部分中使用?(

谢谢,如果您需要更多信息,请让我知道

您不能在不重新分配sp_01的运行时类型的情况下更改它,因为您不能将Derived<e1>分配给Derived<e0>(想想如果它们的大小不相同会发生什么——您已经为Derived<e0>分配了足够的大小,而不是为Derived<e1>分配了!(。

在我看来,你的设计(或你试图用它做的事情(在某个地方有缺陷。然而,如果你真的想在sp_00sp_01之间保持"链接",你可能需要另一个"级别"的指针:

int main() {
    std::shared_ptr<Base> *psp_01;
    std::shared_ptr<Base> sp_00 = std::make_shared<Derived<e0>> ();
    psp_01 = &sp_00;
    (*psp_01)->print();
    std::shared_ptr<Base> sp_10 = std::make_shared<Derived<e1>> ();
    psp_01 = &sp_10;
    (*psp_01)->print();
    sp_10->print();
}

但是,在使用这个之前,我会对我的设计进行两次分析。

您可以dynamic_cast原始指针;类似的东西

Derived* t = dymanic_cast<Derived*>(sp_00.get())

如果不能强制转换,则会得到NULL,如果可以,则会获得有效指针。也就是说,这需要内置RTTI,这将使你的二进制文件更大,而需要这样做是你的设计不正确的标志。