2008-09-24 14 views

cevap

76

Bunu yapmanın bir yolu, kurucuları özel yapmak ve yalnızca bir işaretçi döndüren statik bir yöntemle yapılaşmaya izin vermek olabilir. Örneğin:

class Foo 
{ 
public: 
    ~Foo(); 
    static Foo* createFoo() 
    { 
     return new Foo(); 
    } 
private: 
    Foo(); 
    Foo(const Foo&); 
    Foo& operator=(const Foo&); 
}; 
+7

+ 1 kopyalanamaz hale getirmek için hatırlamak için. –

+8

Ya da daha iyisi bir std :: unique_ptr döndüren bir statik işlev. –

+0

** İlgili soru: [Bir sınıfın 'yeni' operatör aracılığıyla ayrılmasını nasıl önleyebilirim? (Benim RAII sınıfı hep yığını üzerinde tahsis edilir sağlamak istiyorum.)] (Http://stackoverflow.com/questions/124856/how-do-i-prevent-a-class-from-being-allocated- Yeni-kullanıcı-kimliği-gibi) –

10

Sen yapıcı private ardından nesneleri oluşturmak için bir public statik fabrika yöntem sağlar yapabiliriz.

-1

Bir nesne için soyut bir arayüz sağlar başlık dosyası ve öbek üzerinde oluşturulan nesnelere işaretçileri dönmek fabrika fonksiyonlarını oluşturabilir. C++ 11

class Foo 
{ 
    public: 
    ~Foo(); 
    static Foo* createFoo() 
    { 
     return new Foo(); 
    } 

    Foo(const Foo &) = delete; // if needed, put as private 
    Foo & operator=(const Foo &) = delete; // if needed, put as private 
    Foo(Foo &&) = delete; // if needed, put as private 
    Foo & operator=(Foo &&) = delete; // if needed, put as private 

    private: 
    Foo(); 
}; 
14

halka kurucular izin verir ve zamanında atarak yığın tahsisleri durdurulur. Not thread_local, bir C++ 11 anahtar sözcüğüdür. Ayrıca okuyucu için ilginç olabilir

class NoStackBase { 
    static thread_local bool _heap; 
protected: 
    NoStackBase() { 
     bool _stack = _heap; 
     _heap = false; 
     if (_stack) 
      throw std::logic_error("heap allocations only"); 
    } 
public: 
    void* operator new(size_t size) throw (std::bad_alloc) { 
     _heap = true; 
     return ::operator new(size); 
    } 
    void* operator new(size_t size, const std::nothrow_t& nothrow_value) throw() { 
     _heap = true; 
     return ::operator new(size, nothrow_value); 
    } 
    void* operator new(size_t size, void* ptr) throw() { 
     _heap = true; 
     return ::operator new(size, ptr); 
    } 
    void* operator new[](size_t size) throw (std::bad_alloc) { 
     _heap = true; 
     return ::operator new[](size); 
    } 
    void* operator new[](size_t size, const std::nothrow_t& nothrow_value) throw() { 
     _heap = true; 
     return ::operator new[](size, nothrow_value); 
    } 
    void* operator new[](size_t size, void* ptr) throw() { 
     _heap = true; 
     return ::operator new[](size, ptr); 
    } 
}; 

bool thread_local NoStackBase::_heap = false; 
+5

Scott Meyers'in de belirttiği gibi "Madde 11: Silinen işlevleri özel tanımlanmamış olanlara tercih et." "Etkili Modern C++" adlı kitabı, silinen üye işlevlerini "public" ilan etmek daha iyi. --QUOTE-- "Geleneksel olarak, silinen fonksiyonlar' kamuoyunu değil, 'private' ilan edilir. Istemci kodu üyesi işlevini kullanmaya çalışır Bunun bir sebebi. Orada, C + + kontroller erişilebilirlik önce silinen durum. Ne zaman müşteri kodu silinen 'private' işlevini kullanmayı dener, bazı derleyiciler işlevinin erişilebilirliğinin gerçekten kullanılıp kullanılamayacağını etkilemese de, yalnızca 'private' işleviyle ilgili şikayette bulunur. –

+4

--QUOTE-- "Bu yeni işlevler verme çünkü' kamuoyunu genellikle daha iyi hata iletileri neden olacaktır, silinenler ile 'private'-ve-olmayan tanımlı üye işlevlerini yerine eski kodu revize akılda bu rulman değer. " –

+1

Zorunlu. Ver. Moar. Yukarı. Oy. – kevinarpe

4

şu halinde

// Header file 

class IAbstract 
{ 
    virtual void AbstractMethod() = 0; 

public: 
    virtual ~IAbstract(); 
}; 

IAbstract* CreateSubClassA(); 
IAbstract* CreateSubClassB(); 

// Source file 

class SubClassA : public IAbstract 
{ 
    void AbstractMethod() {} 
}; 

class SubClassB : public IAbstract 
{ 
    void AbstractMethod() {} 
}; 

IAbstract* CreateSubClassA() 
{ 
    return new SubClassA; 
} 

IAbstract* CreateSubClassB() 
{ 
    return new SubClassB; 
} 
+0

Veri üyesi olarak '_stack' gerektirdiğine inanmıyorum. 'NoStackBase' yapıcısı içinde basit bir yığın değişkeni olarak yapmalısınız. –

+0

Ayrıca sanallaştırıcıyı sanal yapmak zorunda değilsiniz. Hiç kimse türetilmiş bir sınıfı bir NoStackBase üzerinden silebilir. –

İlgili konular