代码之家  ›  专栏  ›  技术社区  ›  Charles

如何使抽象类正确返回另一个抽象类的具体实例?

  •  0
  • Charles  · 技术社区  · 15 年前

    我最近修改了自己的一个库,尝试将接口与实现分离。我在最后一个问题上遇到了一个类,该类将返回另一个类的实例。

    在接口定义中,我做了一些类似

    struct IFoo
    {
        virtual const IBar& getBar() = 0;
    }
    

    然后在混凝土中,foo getbar看起来像

    const IBar& Foo::getBar()
    {
        Bar ret = Bar();
        return ret;
    }
    

    问题是,一旦getbar完成,ret就会被删除,当复制构造函数尝试使用这样的bar时,会导致很大的崩溃。

    const Bar myBar = myFoo.getBar();
    

    我一直在阅读各种各样的东西,我知道通过引用返回是不受欢迎的,但我没有看到任何其他方式(我不想返回bar*因为我不想手动删除返回值)。

    抽象类返回从另一个抽象类派生的具体类实例的正确方法(如果存在)是什么?

    注意,我确实看到了这个解决方案: returning an abstract class from a function 但我不想使返回值静态化和线程松脱安全性。

    6 回复  |  直到 15 年前
        1
  •  8
  •   Scharron    15 年前

    使用智能指针。 这些是不再使用时删除的指针(参见示例 http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/smart_ptr.htm )

        2
  •  4
  •   Alex Jasmin    15 年前

    还可以按值返回对象。

    一些编译器提供 返回值优化 它在返回对象时优化掉副本。

    编辑:
    对不起的。我略读了一下这个问题,不知怎的错过了继承的事实。假设getbar()可以返回 友善的 IBAR返回 IBAR指针 很有道理。

    通过返回 指向基的指针 混凝土物体保持完好。这个 slicing problem 是避免和原来的 vtbl 指针可用于进行虚拟函数调用。阿尔索 (正如你在评论中提到的) 返回的实例 抽象类 是不可能的。

    我建议您不要返回原始指针, shared_ptr<IBar> 简化内存管理。

    const shared_ptr<IBar> Foo::getBar()
    {
        shared_ptr<IBar> ret(new Bar());
        return ret;
    }
    

    然后这样使用:

    shared_ptr<IBar> pIBar(foo.getBar());
    pIBar->myVirtualFunction();
    

    shared_ptr 是C++0x中最常用的智能指针类型。如果您有足够的最近编译器,它将在 std 命名空间。旧的编译器可能在 tr1 命名空间,它也是Boost的一部分。

        3
  •  2
  •   Adrian    15 年前

    返回对局部变量的引用。一旦函数返回引用,栈就会弹出,这个bar对象就不存在了。

    编辑:我没有读整本书。您可能需要使用智能指针。

    实际上,是否有任何理由需要返回基类引用?您可以通过返回具体类型本身的对象来避免任何智能指针混乱,因为C++允许协变返回类型。

        4
  •  1
  •   Anatoly Fayngelerin    15 年前

    由于要将返回对象的所有权转移给调用方,调用方将必须销毁该对象。换句话说,归还IBAR*是你最好的选择。如果您担心必须手动调用delete,那么应该考虑使用智能指针包,例如boost::shared_ptr。

        5
  •  1
  •   Moisei    15 年前

    如果不想删除,那么必须使用智能指针。 在C++中,只有当对象被占用时,才有对象“删除它自己”的唯一方法。

    http://en.wikipedia.org/wiki/Smart_pointer

        6
  •  1
  •   Simon    15 年前

    移除堆栈时,已在堆栈上创建的对象将被销毁。当函数退出时,堆栈被移除。

    相反,尝试以下方法:

    
    struct Foo : public IFoo
    {
      Bar m_Bar;
    public:
      virtual const IBar& getBar() 
      { 
        return m_Bar;
      }
    }