2013-03-22 10 views
5

Preferisco ridurre al minimo l'uso di #include nei miei file di intestazione, utilizzando le dichiarazioni anticipate laddove possibile, e credo che ciò sia considerato una buona pratica.I puntatori intelligenti infrangono il principio di minimizzare #include nei file di intestazione?

Funziona benissimo se ho una dichiarazione di metodo come:

bool IsFlagSet(MyObject *pObj); 

Tuttavia se ho typedef Ptr<MyObject> MyObjectPtr in MyObject.h ei cambiamenti API a:

bool IsFlagSet(MyObjectPtr pObj); 

Non ora devo a #include "MyObject.h"? C'è un modo per aggirare questo, o è solo il prezzo che si paga per l'utilizzo di puntatori intelligenti?

+0

Perché non 'bool IsFlagSet (Ptr pObj);'? –

+0

Se si passa il puntatore intelligente per riferimento, non funzionerà come prima? –

+2

P.S. A meno che la funzione non cambi la proprietà del puntatore intelligente, non è necessario utilizzare un puntatore intelligente nell'interfaccia. Usa invece uno stupido e usa il puntatore intelligente 'get' sul sito di chiamata. –

risposta

9

No, non è necessario. È possibile definire un tipo di alias per una classe incompleta, e gli argomenti modello può essere di tipo incompleto (vedi paragrafo 14.3.1/2 del C++ 11 Standard):

#include <memory> 

struct C; 

typedef std::shared_ptr<C> ptrC; // C is incomplete here 

struct C { void foo() { } }; 

int main() 
{ 
    ptrC p = std::make_shared<C>(); 
    p->foo(); 
} 

Come detto correttamente Pubby nei commenti , dichiarazioni di funzione non richiedono forme menzionate loro firma per essere completa sia:

struct C; 

void foo(C); // C is incomplete here 

struct C { }; 

#include <iostream> 

void foo(C) 
{ 
    std::cout << "foo(C)" << std::endl; 
} 

int main() 
{ 
    C c; 
    foo(c); 
} 
+0

Si potrebbe voler aggiungere che le dichiarazioni di funzione non hanno bisogno di tipi completi neanche. – Pubby

+0

@Pubby: Grazie, ho aggiunto alla risposta –

+0

Interessante, grazie. –

3

No, std::shared_ptr<T> è esplicitamente progettato per funzionare quando T è solo in avanti-dichiarati. Naturalmente, questo non funziona in tutti i casi, ma il principio è lo stesso di un semplice puntatore. Se T viene inoltrato, puoi fare qualsiasi cosa con std::shared_ptr<T> che potresti fare con T*.

0

è possibile utilizzare typedef con tipo incompleto.

Ma non è meglio utilizzare il nome completo del tipo di puntatore intelligente?

MyClassPtr è ovviamente molto più breve, ma in realtà std::unique_ptr<MyClass> ci dice come utilizzare questo puntatore. Quindi per nomi non molto lunghi suggerisco di usare nomi completi di puntatori intelligenti.

+0

Non aiuta se qualcun altro ha già scritto il codice. Questo modello 'typedef Ptr TypePtr' è uno che vedo in diverse librerie sia open-source che proprietarie. –

Problemi correlati