2012-08-04 3 views
0

Nous pouvons probablement convenir que la construction de copie par défaut est mauvaise la plupart du temps en C++, il est donc préférable de la désactiver explicitement avec C++ 11 =delete ou non-copiable des classes comme boost::noncopyable. La question est: que se passe-t-il dans les scénarios avancés lorsque nous utilisons plusieurs classes d'héritage ou de public abstraite?Classes C++ non-copiables et héritage multiple, classes abstraites

//Class uncopyable 
class uncopyable {...}; 

//Interface1 
class IInterface1 : private uncopyable 
{ 
public: 
IInterface1(...) 
virtual ~IInterface1(...) = 0; 
}; 

//Interface2 
class IInterface2 : private uncopyable 
{ 
public: 
IInterface2(...) 
virtual ~IInterface2(...) = 0; 
}; 

//Fancy implementation 
//FImpl 
class FImpl : public IInterface1, public IInterface2, private : uncopyable 
{ 
public: 
FImpl(...) {...} 
~FImpl(...) {...}; 
}; 
  • Est-il une bonne pratique de faire toutes les interfaces non copiable (il semble que ce est, pour éviter le découpage)?
  • Est-il une bonne pratique d'ajouter incopiable à chaque classe dérivée (de sauvegarde explicite, mais des causes multiples héritage et problèmes diamants?)
+1

Vos interfaces ne ressemblent pas du tout à des interfaces. Ils définissent des constructeurs et n'ont pas de méthodes virtuelles pures (seulement une sorte de destructeur qui ressemble à une violation de syntaxe). – Juliano

+0

'~ IInterface1 (...) = 0' est juste une erreur de syntaxe. Et vous ne voulez pas rendre les destructeurs purs virtuels. –

+0

Ok, corrigé. En utilisant le pseudo-code, pas un vrai code. – Coder

Répondre

1

Non, ce n'est pas une bonne idée de faire l'interface non copiable. Par exemple, cela empêche le clonage.

Et non, ce n'est pas une bonne idée de dériver de non-copiable dans chaque classe dérivée, parce que c'est juste redondant. Toutefois, afin d'empêcher que Visual C++ produise des avertissements stupides, il peut être judicieux de déclarer un constructeur de copie et un opérateur d'affectation de copie dans chaque classe qui ne peut pas être copiée.

+0

Qu'est-ce que le clonage? Code comme 'IInterface1 * ptr = nouveau FImpl();' 'IInterface1 instA = * ptr;' est-ce que c'est faux pour autant que je sache? – Coder

+0

@Coder: c'est très souvent une bonne idée de vérifier la [FAQ] (http://www.parashift.com/c++-faq-lite/virtual-ctors.html) –

+0

Ok, il est bon de savoir qu'une telle approche existe, Je n'en ai jamais entendu parler auparavant. Cependant, j'essaie généralement d'éviter le clonage, car cela signifie généralement des copies profondes, des verrous de section critiques, des constructeurs de copie non triviaux (comment copier un mutex verrouillé ou gérer un pinceau GDI?), Et ainsi de suite. J'utilise généralement des références à const chaque fois que possible. – Coder

0

Une classe virtuelle pure (interface) n'a pas besoin d'imposer la gestion de la mémoire pour l'utilisation de l'interface. Les implémentations d'interfaces virtuelles pures devraient déterminer leurs propres exigences de gestion de la mémoire (comme copier et assigner). Cela dit, la sémantique des valeurs permet aux implémentations d'éviter complètement cette situation. Une classe de valeur (copiable, assignable, etc.) est plus facile à raisonner et à utiliser. Toutes les classes de la bibliothèque C++ sont des classes de valeur. Un bon exemple d'une classe de gestion de la mémoire pour elle-même est la classe de chaînes vénérable. Le vecteur est aussi un bon exemple. Ces classes ont des exigences complexes en matière de gestion de la mémoire interne, mais en tant qu'utilisateur de ces classes, je n'ai pas à me préoccuper de cet aspect de la classe. Je peux me concentrer sur la façon d'utiliser la classe.

J'aime ce presentation de C++ Now qui montre comment le polymorphisme est aussi un détail d'implémentation. Cela inclut la possibilité pour un client d'implémenter des classes qui peuvent participer au polymorphisme sans avoir besoin d'une classe d'interface (ou d'une classe de base d'ailleurs).

+0

Mais les chaînes et les vecteurs sont des classes dont vous ne pouvez pas dériver d'autres classes. – Coder