2012-05-11 10 views
5

Supponiamo che io ho una classe con un metodo factoryPrevenire istanza di un oggetto fuori del suo metodo factory

class A { 
public: 
    static A* newA() 
    { 
    // Some code, logging, ... 
    return new A(); 
    } 
} 

E 'possibile evitare che l'istanza di un oggetto di questa classe con un new, in modo che il metodo di fabbrica è l'unico metodo per creare un'istanza dell'oggetto?

+2

Singletons sono il male. Vedi qui: http://programmers.stackexchange.com/questions/40373/so-singletons-are-bad-then-what –

+2

@Truth: non sembra un singleton. –

+0

@OliCharlesworth: una factory che restituisce un'istanza di se stessa e impedisce a chiunque altro di renderla istantanea? Sembra pericolosamente vicino. –

risposta

8

Sicuro; basta fare il privato costruttore (protetta se si tratta di una classe di base):

class A { 
public: 
    static A* newA() 
    { 
    // Some code, logging, ... 
    return new A(); 
    } 

private: 
    A() {} // Default constructor 
}; 

Si dovrebbe fare il costruttore di copia privata/protetta e, se necessario.

E come sempre, è consigliabile prendere in considerazione la possibilità di restituire un puntatore intelligente anziché un puntatore raw, al fine di semplificare i problemi di gestione della memoria.

+0

Questa risposta è solo un urlo di 'std :: unique_ptr' ... Modifica: Meh, non andare fantasma-modifica la tua risposta. : P – Xeo

+0

Grazie per la risposta. Per quanto riguarda i puntatori intelligenti - lo so. Li userei normalmente. Ma la gestione della memoria per questo particolare oggetto è un po 'complicata e non può usare 'shared_ptr'everywhere per motivi di prestazioni. – Tibor

+0

Mi sono sempre chiesto, supponiamo che la tua fabbrica restituisca un unique_ptr ma in realtà uno vuole shared_ptr (o viceversa), come si farebbe? – stijn

3

Si consiglia inoltre di fare il costruttore di copia privata, come bene o con la nuova sintassi C++ 11 si può dire esplicitamente al compilatore di non copiarlo e rendere il costruttore di default privato con qualcosa di simile:

struct NonCopyable { 
    NonCopyable & operator=(const NonCopyable&) = delete; 
    NonCopyable(const NonCopyable&) = delete; 
    NonCopyable() = default; 
}; 

class A : NonCopyable { 
public: 
    static std::shared_ptr<A> newA() 
    { 
    // Some code, logging, ... 
    return std::make_shared<A>(); 
    } 

private: 
    A() {} // Default constructor 
}; 

Il modo in cui C++ 03 era di solito qualcosa di simile:

class A { 
public: 
    static A* newA() 
    { 
    // Some code, logging, ... 
    return new A(); 
    } 

private: 
    A() {}      // no outsider default constructor 
    A(const A& rhs);    // no copy 
    A& operator=(const A& rhs); // no assignment 
}; 

int main() 
{ 
    A x;  // C2248 
    A y(x);  // C2248 
    x = y;  // C2248 
    A* p = A::newA(); // OK 
    std::cin.get(); 
    return 0; 
} 
+0

Con C++ 11 si dovrebbe davvero evitare di restituire un puntatore nudo. –

+0

Buon punto, in realtà eviterei la maggior parte di questo e semplicemente uso 'std :: unique_ptr' nella maggior parte dei casi probabilmente. – AJG85