简体   繁体   English

从C ++类返回shared_ptr

[英]Return a shared_ptr from a class C++

I have a question which has to do with returning a shared pointer from a class. 我有一个问题与从类返回共享指针有关。 Part of my class looks like this: 我班的一部分看起来像这样:

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

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

where both m_derivedInterface and m_spBase are private members of my class, ie: 其中m_derivedInterfacem_spBase都是我的类的私有成员,即:

private:

   IBaseInterfaceSP m_spBase ;

   DerivedInterface m_derivedInterface;

Also, DerivedInterface inherits from IBaseInterfaceSP . 同样, DerivedInterface继承自IBaseInterfaceSP

getInterface is a public function of my class. getInterface是我班的一个公共函数。

Is this the right way to return a pointer from my class? 这是从类中返回指针的正确方法吗? Will there be any problems with slicing or anything similar? 切片或类似的东西会有问题吗?

PS I am sorry if something is unclear ( I am not allowed to post all the code here in public, only some parts), if so, just let me know. PS很抱歉,如果有不清楚的地方(不允许将所有代码公开发布在这里,只有某些部分),如果可以,请告诉我。

I can see several problems with this code. 我可以看到此代码的几个问题。

1. Lazy initialization 1.延迟初始化

Each time you call getInterface, you create a new instance of your IBaseInterface class. 每次调用getInterface时,都会创建一个IBaseInterface类的新实例。 As a user of your class, I would not expect this behavior from a method called "get". 作为您班级的用户,我不会从名为“ get”的方法获得这种行为。

I guess you wanted to implement lazy initialization, in which case you would do it like this: 我猜您想实现延迟初始化,在这种情况下,您可以这样进行:

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

2. Naming conventions 2.命名约定

You are instantiating a class called IBaseInterface, which sounds like an abstract class (the "I" prefix was historically used for interfaces). 您正在实例化一个名为IBaseInterface的类,这听起来像一个抽象类(“ I”前缀在历史上一直用于接口)。 You should probably rename your class so that it doesn't sound abstract. 您可能应该重命名您的类,以使其听起来不抽象。 Also, the "I" prefix is redundant with the "Interface" suffix. 另外,“ I”前缀在“ Interface”后缀中是多余的。

However, in what I consider "good" OOP, users do not need to know that you are handing them an interface. 但是,在我认为“好的” OOP中,用户不需要知道您正在向他们提供接口。 There is thus no need for a naming convention that differentiates concrete from abstract classes. 因此,不需要将具体类与抽象类区分开的命名约定。

3. Ownership semantics 3.所有权语义

Shared pointers are meant for shared ownership : when you return a shared pointer, you are telling the users of your class that they will own the returned object, too. 共享指针用于共享所有权 :返回共享指针时,您是在告诉类用户他们也将拥有返回的对象。 Usually, that is not needed. 通常,不需要。 In most cases you would return a non-owning pointer, aka raw pointer. 在大多数情况下,您将返回非所有者指针,也就是原始指针。 For example: 例如:

IBaseInterface* getInterface()
{
    return m_spBase.get(); // Instantiation done elsewhere, for example in constructor
}

4. Slicing 4.切片

There is indeed slicing happening here. 确实有切片发生在这里。 This line: 这行:

m_spBase = std::make_shared<IBaseInterface>( m_derivedInterface );

Actually expands to code that contains something equivalent to this: 实际上扩展为包含与此等效的代码:

auto newInstance = new IBaseInterface(m_derivedInterface );

In turn, the line above will call the copy constructor of the IBaseInterface class, whose signature is similar to: 反过来,上面的行将调用IBaseInterface类的副本构造函数,其签名类似于:

IBaseInterface(IBaseInterface& other)

Thus, m_derivedInterface is interpreted as an IBaseInterface reference in the context of that call. 因此,在该调用的上下文中,m_derivedInterface被解释为IBaseInterface引用。 Only the members of IBaseInterface will thus be copied during the call to "new", thereby losing all the information stored in the derived class, DerivedInterface. 因此,在调用“ new”期间仅将复制IBaseInterface的成员,从而丢失存储在派生类DerivedInterface中的所有信息。


All that said, it seems to me that what you really want is direct access to the m_derivedInterface object. 综上所述,在我看来,您真正想要的是直接访问m_derivedInterface对象。 What you are doing right now is, you copy the instance into another object and return the new object. 您现在正在做的是,将实例复制到另一个对象中并返回新对象。 I think what you really want is this: 我认为您真正想要的是:

IBaseInterface* getInterface()
{
    return &m_derivedInterface;
}

If you insist on using shared ownership, just store a shared pointer to m_derivedInterface instead of a value: 如果您坚持使用共享所有权,只需存储指向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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM