【问题标题】:How do I get member of child class from unique pointer to base class?如何从指向基类的唯一指针中获取子类的成员?
【发布时间】:2015-02-13 17:37:46
【问题描述】:

我有一个对象,它作为基类的 unique_ptr 存储在地图中。

class Base
{
    int foo;
};

map <string, unique_ptr<Base> > Objects;

但是,这些对象实际上属于不同的子类。

class Child1 : public Base
{
    int bar1;   
};
class Child2 : public Base;
{
    int bar2;
};

Objects.insert(make_pair("Child1", unique_ptr<Base>(new Child1())));
Objects.insert(make_pair("Child2", unique_ptr<Base>(new Child2())));

现在,在代码中很远的地方,我想访问 Child1 的一个成员变量,它是该类所独有的。

cout << "Bar1 is:" << Objects["Child1"]->bar1 << endl;

但我得到了错误:

ERROR: 'class Base' has no member 'bar1'

所以我尝试使用 dynamic_cast,但当然,你不能在 unique_ptr 上使用 dynamic_cast。

那我该怎么办?

【问题讨论】:

  • 当您不想对所有基类指针都一视同仁时,您就违背了多态性的目的。使用 Boost.Variant 或其他类型安全的联合,至少比你自己做的更简单。
  • 会员是private,那么您打算如何访问它?
  • 由于您没有使用指向基的指针,因此您只能访问基成员。这称为对象切片。 stackoverflow.com/questions/274626/what-is-object-slicing
  • dynamic_cast 方法仅在存在任何此代码没有的虚函数时才有效。给 Base 一个virtual ~Base() 然后编译器将为 Child 提供它自己的虚拟析构函数,动态转换将起作用。
  • @Yaxlat:存储基类指针的好处是您将所有对象(基类和派生类)视为相同。将它们全部放在一个列表中既好又方便。但是,您突然需要关心指针实际上是指向派生类型 A 还是 B,这意味着您没有对它们一视同仁,因此您没有进行优化。根据经验,如果您正在开发一个大型系统,那么您以后会非常头疼。只需将派生对象存储在它们自己的数组中,稍后您会很高兴它如此简单。

标签: c++


【解决方案1】:
  1. unique_ptr 中获取指向基类的指针。

    Base* basePtr = Objects["Child1"].get();
    
  2. 在指针上做一个dynamic_cast

    Child1* child1Ptr = dynamic_cast<Child1*>(basePtr);
    
  3. 访问Child1 类的成员。

    if ( child1Ptr != nullptr )
    {
       // ... Use child1Ptr
    }
    

确保创建基类virtual 的析构函数。否则,当unique_ptrs 被销毁时,派生类的析构函数将永远不会被调用。此外,正如 @AndyG 在 cmets 中所观察到的,dynamic_cast 在没有任何虚函数的情况下将无法工作。

class Base
{
    public:
        virtual ~Base(){}

    private:
       int foo;
};

【讨论】:

  • 析构函数是虚拟的!非常感谢您的帮助,它有效!我正在考虑按照这些思路做一些事情,但不知道如何将 unique_ptr 转换为原始指针,这是第 1 步。
猜你喜欢
  • 2018-03-24
  • 2021-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多