代码之家  ›  专栏  ›  技术社区  ›  Dimitri Tcaciuc

命名构造函数和继承

  •  1
  • Dimitri Tcaciuc  · 技术社区  · 16 年前

    我正在开发C++框架,并希望将自动内存管理应用于许多核心类。到目前为止,我的标准方法是

    class Foo 
    {
    
    public:
    
      static
      shared_ptr<Foo> init() 
      {
        return shared_ptr<Foo>(new Foo);
      }
    
      ~Foo() 
      {
      }
    
    protected:
    
      Foo()
      {
      }
    
    };
    
    
    // Example of use
    shared_ptr<Foo> f = Foo::init();
    

    然而,当我子类化Foo时,上面的代码就中断了,因为即使是tho init() 继承后,它仍然会返回 shared_ptr<Foo> 它包含一个指向以下实例的指针 Foo .

    有人能想出一个优雅的解决方案吗?我是否应该继续使用(半)手动包装类的实例 shared_ptr

    template <typename T>
    shared_ptr<T> make_shared(T* ptr)
    {
      return shared_ptr<T>(ptr)
    }
    
    // Example
    shared_ptr<T> 
      f1 = make_shared(new Foo()),
      f2 = make_shared(new Foo(1,2));
    
    8 回复  |  直到 16 年前
        1
  •  4
  •   Tomek    16 年前

    template<class T>
    class creator
    {
      public:
        static shared_ptr<T> init()
        {
          return(shared_ptr<T>(new T));
        }
    };
    
    class A : public creator<A>
    {
    };
    
    class B : public A, public creator<B>
    {
      public:
        using make_shared<B>::init;
    };
    
    // example use
    shared_ptr<A> a = A::init();
    shared_ptr<B> b = B::init();
    

    但与您提出的独立模板相比,这并不一定能为您节省任何东西。

    编辑:我错过了之前的答案,这似乎是同一个想法。

        2
  •  2
  •   Patrick    16 年前

    我不明白这能实现什么,除了简单地声明shared_ptr之外,使用此init函数似乎不会获得任何额外的内存管理。

    int main( void )
    {
        shared_ptr<foo> a = foo::init();
        shared_ptr<foo> b( new foo );
    }
    

    有什么区别。shared_ptr提供内存管理,而不是init中的任何东西。

        3
  •  2
  •   Antti Huima    16 年前

    目标似乎是让类的用户无法直接调用构造函数,而只公开一个返回shared_ptr的例程。

    但是,如果你想应用这种模式,你需要在所有子类中复制它。子类不能自动“继承”init(),因此init()仍将调用子类构造函数,因为init()不是虚拟方法,在没有对象的情况下调用。

    shared_ptr<X> x = new X();
    

    这使得认知负担低,可读性强,并且保持灵活性。无论如何,这就是我们公司使用引用计数对象进行编程的方式。

        4
  •  1
  •   Sandeep Datta    16 年前

    怎么样。..

    template<typename Derived>
    class Foo 
    {
    public:
    
        static shared_ptr<Derived> init() 
        {
            return shared_ptr<Derived>(new Derived);
        }
    
        ~Foo() 
        {
        }
    
    protected:
    
        Foo()
        {
        }
    
    };
    
    
    class Bar : public Foo<Bar>
    {
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        shared_ptr<Bar> b = Foo<Bar>::init(); 
        return 0;
    }
    
        5
  •  1
  •   sharptooth    16 年前

    为什么不引入一个带有虚拟析构函数的公共基类,从中继承所有必要的类,并简单地使用new?

        6
  •  1
  •   Michel    16 年前

    使用以下命令强制创建对象通常不是一个好主意 shared_ptr 通过隐藏构造函数。我是根据在这里与一家内部公司图书馆合作的个人经验说的,该图书馆正是这样做的。如果你想确保人们总是包装他们分配的对象,只需确保存储这些类型实例的所有参数和成员都期望 weak_ptr 而不是裸指针或引用。您可能还希望从中派生这些类 enable_shared_from_this ,因为在一个所有对象都共享的系统中,在某些时候,你必须传递 this 指向这些其他对象的方法之一,并且由于它们仅被设计为接受 shared_ptr internal_weak_this 以确保它不会被破坏。

        7
  •  0
  •   Tanveer Badar    16 年前

    class Foo
    {
    public:
        static shared_ptr< Foo > instantiate( /* potential arguments */ )
        {
               return shared_ptr< Foo >( new Foo( /* potential arguments */ );
        }
    
    // blah blah blah
    };
    
    class Bar : public Foo
    {
    public:
        static shared_ptr< Bar > instantiate( /* potential arguments */ )
        {
               return shared_ptr< Bar >( new Bar( /* potential arguments */ );
        }
    
    // blah blah blah
    };
    

    如果您仍然有任何困惑,请在sourceforge上搜索CppCodeProvider,看看它是如何完成的。

        8
  •  0
  •   Stefan Monov    15 年前

    QPixmap foo() {
        QPixmap pixmap(10, 10);
        return pixmap;
    }
    
    void bar() {
        QPixmap a = foo(); // no copying occurs, internal refcount incremented.
        QPixmap b = a;     // ditto.
        QPainter p(&b);
        p.drawPoint(5, 5); // data can no longer be shared, so a copy is made.
        // at this point 'a' is still unchanged!
        p.end();
    }
    

    与Qt中的许多东西一样,这模仿了Java对象模型,但它通过实现更进一步 copy-on-write (它称之为 implicit sharing ).这是为了减少API行为对C++程序员的干扰,因为他们不习惯调用 clone() .

    d-pointer idiom ,一举两得-您提供自动内存管理, 您将实现与用户隔离开来( pimpl ).

    您可以在此处查看QPixmap的实际实现: qpixmap.cpp , qpixmap.h .