2010-04-14 8 views
4

J'ai trouvé ce code hereclasse qui ne peut être dérivé

class Usable; 

class Usable_lock { 
    friend class Usable; 
private: 
    Usable_lock() {} 
    Usable_lock(const Usable_lock&) {} 
}; 

class Usable : public virtual Usable_lock { 
    // ... 
public: 
    Usable(); 
    Usable(char*); 
    // ... 
}; 

Usable a; 

class DD : public Usable { }; 

DD dd; // error: DD::DD() cannot access 
     // Usable_lock::Usable_lock(): private member 

Quelqu'un pourrait me expliquer ce code?

EDIT: Une autre question que j'ai est ce qui est une dérivation virtuelle et quand est-il nécessaire?

+2

Notez que cette classe ne fait pas ce qu'elle dit sur l'étain - elle n'empêche pas la dérivation. Si tel était le cas, un message d'erreur s'afficherait au point où la classe est réellement dérivée. –

+0

Ceci est un article sur l'héritage virtuel: http://en.wikipedia.org/wiki/Virtual_inheritance. Pourquoi l'héritage virtuel est utilisé ici? Pour éviter les problèmes d'héritage multiples, lorsque la classe Usable est dérivée d'une autre classe, à l'exception de Usable_lock. –

+0

Essayez d'éditer pour utiliser ce lien à la place: http://www2.research.att.com/~bs/bs_faq2.html#no-derivation "Il repose sur le fait que la classe la plus dérivée dans une hiérarchie doit construire un base virtuelle. " La classe DD le fait. –

Répondre

5

C'est une propriété de la dérivation virtual.

L'idée de virtual dérivation est de résoudre le "Dreaded motif diamant":

struct Base {}; 

struct D1: Base {}; 
struct D2: Base {}; 

struct TopDiamond: D1, D2 {}; 

Le problème ici est que TopDiamond a 2 instance de Base ici.

Pour résoudre ce problème, "MultiInheritance" très particulier, C++ utilise le mot-clé virtual et ce que l'on appelle ainsi "l'héritage virtuel".

Si nous changeons la façon dont D1 et D2 sont définis tels que:

struct D1: virtual Base {}; 
struct D2: virtual Base {}; 

Ensuite, il n'y aura qu'une seule instance de Base au sein TopDiamond: le travail de l'instanciation en fait il est laissé au sommet constructeur (ici TopDiamond).

Ainsi, le petit truc que vous avez montré simplement expliqué ici:

  • parce Usable dérive pratiquement de Usable_lock, il est à sa classe dérivée instancier la Usable_lock partie de l'objet
  • parce que Usable_lock constructeur est private, lui-même et ne Usable (ami) peut accéder au constructeur

Il est intelligent, je Je n'y avais jamais pensé. Je me demande quel est le coût de l'héritage virtual ici (surcharge mémoire/vitesse supplémentaire)?

+0

Yup, cela résume assez bien, je passerais un peu moins de temps à expliquer ce que l'héritage virtuel est généralement bon pour, mais alors j'étais paresseux pour écrire une réponse moi-même. ':)' +1 de moi. – sbi

1

classe Usable_lock « s Constructor est déclarée en privé Il n'est pas accessible à l'extérieur

Usable_lock class 

lorsque vous faites l'objet de

DD dd; 

Il appellera constructeur de Usable et Usable_Lock les deux (parce que DD dérivé de Usable et Usable Dérivé de Usable_lock)

et donc il ne peut pas accéder à Constructor de Usable_Lock .. et il vous donnera erreur

+0

Cependant, 'class Usable' est un ami et devrait donc pouvoir y accéder. 'DD' ne devrait pas accéder à' Usable_lock', c'est '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' utilisable '(? –

+2

@Pasi: 'Usable_lock' est une base' virtual', donc les classes dérivées doivent pouvoir accéder à l'un de ses constructeurs. Malheureusement, la réponse de mihirpmehta ne mentionne pas cela. – sbi

+0

@sbi oui très vrai ... j'ai omis de mentionner que ...; ( –

1

Il y a ici deux points:

1) Pourquoi par exemple utilisable peut être créé, mais il implique constructeur Usable_lock privé ? Parce qu'Usable est ami de Usable_lock.

2) Pourquoi l'instance dérivée de l'utilisable ne peut-elle être créée? Parce qu'il implique un constructeur Usable_lock privé.

+1

Indice - il s'agit de la dérivation "virtuelle" –

Questions connexes