Il primo dei dieci comandamenti per programmatori C ++ di Steve Oualline è stato trascritto correttamente?

5

Non ho il libro "Practical C ++ Programming" di Steve Oualline ma stavo leggendo i suoi dieci comandamenti per i programmatori C ++ su link e mi chiedevo se il primo è stato correttamente trascritto? Per riferimento la trascrizione è:

"1. Non ti baserai sui metodi predefiniti del compilatore per la costruzione, la distruzione, la costruzione di copie o l'assegnazione per nessuna delle classi più semplici: dimenticheresti questi" quattro grandi "metodi per qualsiasi classe non banale."

Sembra che stia sostenendo la definizione manuale della costruzione della copia e dell'assegnazione della copia. È una corretta interpretazione del suo primo comandamento?

Modifica: Anche se al momento sto lasciando la risposta di Adrian come quella accettata, vorrei che chiunque osservasse questa domanda leggesse quella di Jerry. Mi sono chiesto specificamente se il testo sopra riportato è stato trascritto in modo accurato e non sul merito (che è probabilmente una discussione più interessante). Ma Jerry fa alcuni buoni punti sul merito (o sulla sua mancanza) che sono simili alle mie opinioni su di esso. Volevo solo assicurarmi di avere la citazione giusto prima di aver costruito una discussione approfondita sul motivo per cui non sono d'accordo.

    
posta Bowie Owens 05.08.2013 - 23:32
fonte

2 risposte

8

Per la classe "qualsiasi non banale" sono certo che è esattamente ciò che sta suggerendo - e sarebbe certamente una buona pratica scrivere un costruttore di copie esplicite o un incarico sovraccarico per una classe non banale.

    
risposta data 06.08.2013 - 00:07
fonte
11

A me sembra che sia probabilmente trascritto con precisione. Sfortunatamente, il consiglio è per lo più obsoleto (nella misura in cui è stato sempre buono). Il libro in questione è stato scritto nel 1995 e aggiornato nel 1997. Molto è successo negli ultimi 15 anni che rende questo consiglio obsoleto.

Il consiglio si basa sulla nozione di una classe non banale che implementa la "proprietà remota" - cioè, contenente uno o più puntatori ai dati di sua proprietà che saranno allocati nel negozio gratuito. Esempi ovvi sono cose come std::string e std::vector , ognuno dei quali normalmente alloca un blocco di memoria per contenere i dati nel contenitore (e l'oggetto string o vector stesso contiene solo il puntatore e un piccolo numero di dati contabili , ad esempio la dimensione del blocco assegnato e il numero di elementi nel blocco attualmente in uso).

La ragione per cui dico che è obsoleto è che nella maggior parte dei casi, non dovresti usare i puntatori raw per la proprietà remota. Invece, dovresti in genere utilizzare un puntatore intelligente (ad esempio unique_ptr o shared_ptr ) per gestire la proprietà remota. Questo puntatore intelligente dovrebbe implementare la "politica" di proprietà remota (copia, assegnazione, distruzione) dei dati che possiede.

Quindi la classe non banale aggregherà semplicemente un'istanza (o più di una, a seconda) per gestire i suoi dati remoti. Nel processo, ottiene la corretta politica di proprietà implementata da quei puntatori intelligenti. Di conseguenza, di solito non avrà bisogno di implementare qualsiasi di quanto sopra.

Questo lascia tipicamente solo la costruzione che deve essere gestita dalla classe non banale. Anche in questo caso si limitano a "distribuire" i dati alla classe base e / o agli oggetti aggregati, quindi il corpo del ctor è spesso vuoto:

class foo {
    std::unique_ptr<T> data;
public:
    foo(T const &input) : data(make_unique(input)) : {}
};

In conclusione: una classe non banale dovrebbe presentare una visione logica di un'astrazione. Dovrebbe occuparsi quasi esclusivamente della logica dell'astrazione che rappresenta. Dovrebbe raramente (se mai) trattare direttamente direttamente problemi di basso livello, orientati alla lingua come allocazione, cancellazione e copia della memoria necessaria per rappresentare l'astrazione che rappresenta.

Questi problemi dovrebbero essere quasi sempre affrontati da classi di livello inferiore progettate anche per rappresentare un'astrazione - ma in questo caso, un'astrazione abbastanza semplice di "dati di proprietà remota", che sa come gestire cose come copiare, assegnare e distruggendo i dati che possiede, con poco o nessun aiuto dalla classe che lo possiede (ad esempio, la classe proprietaria che passa alcuni argomenti di funzione per dire come distruggere i dati di proprietà). Almeno in molti (la maggior parte?) Casi tipici, una delle classi puntatore nella libreria standard (come il summenzionato unique_ptr o shared_ptr ) sarà del tutto adeguata a questo compito.

Di conseguenza, raramente è necessario definire il proprio costruttore di copia, l'assegnazione della copia o il distruttore. Questi problemi dovrebbero in genere essere gestiti da classi di livello inferiore dedicate alla fornitura della proprietà remota.

Riferimenti e ulteriori letture:

  1. link
  2. link
risposta data 07.08.2013 - 22:54
fonte

Leggi altre domande sui tag