我有一个问题与从类返回共享指针有关。
我类的一部分看起来像这样:

typedef std::shared_ptr<IBaseInterface> IBaseInterfaceSP;
...

IBaseInterfaceSP getMyInterface()
   {
      m_spBase = std::make_shared<IBaseInterfaceSP>( m_derivedInterface);
      return m_spBase;
   }

其中m_derivedInterfacem_spBase均为我类的私有(private)成员,即:
private:

   IBaseInterfaceSP m_spBase ;

   DerivedInterface m_derivedInterface;

另外,DerivedInterface继承自IBaseInterfaceSP
getInterface是我的类(class)的公共(public)功能。

这是从类中返回指针的正确方法吗? slice 或类似的东西会有问题吗?

附言如果有不清楚的地方,我很抱歉(不允许我在此处公开所有代码,仅发布某些部分),如果是这样,请告诉我。

最佳答案

我可以看到此代码的几个问题。

1.延迟初始化

每次调用getInterface时,都会创建一个IBaseInterface类的新实例。作为您类(class)的用户,我不会从名为“get”的方法获得这种行为。

我猜您想实现延迟初始化,在这种情况下,您可以这样做:

IBaseInterfaceSP getInterface()
{
    if (!m_spBase)
    {
        m_spBase= std::make_shared<IBaseInterface>( m_derivedInterface );
    }
    return m_spBase;
}

2.命名约定

您正在实例化一个称为IBaseInterface的类,它听起来像一个抽象类(“I”前缀在历史上一直用于接口(interface))。您可能应该重命名您的类,以使其听起来不抽象。另外,“I”前缀在“Interface”后缀中是多余的。

但是,在我认为“好的” OOP中,用户不需要知道您正在向他们提供接口(interface)。因此,无需将具体类与抽象类区分开的命名约定。

3.所有权语义

共享指针用于共享的所有权:返回共享指针时,您告诉类的用户他们也将拥有返回的对象。通常,不需要。在大多数情况下,您将返回一个非所有者指针,也就是原始指针。例如:
IBaseInterface* getInterface()
{
    return m_spBase.get(); // Instantiation done elsewhere, for example in constructor
}

4. slice

确实有 slice 在这里发生。这行:
m_spBase = std::make_shared<IBaseInterface>( m_derivedInterface );
实际上扩展为包含与此等效的代码:
auto newInstance = new IBaseInterface(m_derivedInterface );
反过来,上面的行将调用IBaseInterface类的副本构造函数,其签名类似于:
IBaseInterface(IBaseInterface& other)
因此,在该调用的上下文中,m_derivedInterface被解释为IBaseInterface引用。因此,在调用“new”期间仅将复制IBaseInterface的成员,从而丢失存储在派生类DerivedInterface中的所有信息。

综上所述,在我看来,您真正想要的是直接访问m_derivedInterface对象。您现在正在做的是,将实例复制到另一个对象中并返回新对象。我认为您真正想要的是:
IBaseInterface* getInterface()
{
    return &m_derivedInterface;
}

如果您坚持使用共享所有权,只需存储指向m_derivedInterface的共享指针而不是值:
MyClass(Args args)
{
    m_derivedInterface.reset(new DerivedInterface(args));
}

std::shared_ptr<IBaseInterface> getInterface()
{
    return m_derivedInterface;
}

std::shared_ptr<IBaseInterface> m_derivedInterface;

10-08 09:25