2010-06-30 4 views
18

j'ai quelque chose comme ça (simplifié)fonctions prioritaires virtuelles C++ avec le même nom

class A 
{ 
    public: 
    virtual void Function() = 0; 
}; 

class B 
{ 
    public: 
    virtual void Function() = 0; 
}; 

class Impl : public A , public B 
{ 
    public: 
     ???? 
}; 

Comment puis-je mettre en œuvre la fonction() A et la fonction() B? Visual C++ vous permet de définir uniquement la fonction spécifique en ligne (c'est-à-dire pas dans le fichier cpp), mais je suppose que c'est une extension. GCC se plaint à ce sujet. Existe-t-il une méthode C++ standard pour dire au compilateur quelle fonction je veux remplacer?

(Visual C++ 2008)

class Impl : public A , public B 
{ 
    public: 
    void A::Function() { cout << "A::Function" << endl; } 
    void B::Function() { cout << "B::Function" << endl; } 
}; 

Merci!

+0

aussi, j'ai finalement réalisé comment QueryInterface arrive à fonctionner lors de l'implémentation de plusieurs interfaces COM! :) – QbProg

Répondre

30

Vous ne pouvez pas utiliser de noms qualifiés ici. Je vous écris void Function() { ... } vous remplacent les deux fonctions. Herb Sutter montre how it can be solved.

Une autre option est de renommer ces fonctions, car apparemment, elles font quelque chose de différent (sinon je ne vois pas le problème de surcharger les deux avec un comportement identique).

+0

merci pour le lien :) – QbProg

-1

Si A et B sont des interfaces, alors j'utiliserais la dérivation virtuelle pour les "joindre" (les faire se chevaucher). Si vous avez besoin de différentes implémentations pour votre Function si vous appelez via un pointeur vers A ou vers B alors je vous recommande fortement de choisir un autre design. Cela va faire mal autrement.

Impl "dérive" A et B signifie Impl "est un" A et B. Je suppose que tu ne le penses pas.

Impl "implémente l'interface" A et B signifie Impl "se comporte comme" A et B. alors la même interface devrait signifier le même comportement. Dans les deux cas, un comportement différent selon le type de pointeur utilisé serait "schizophrénique" et est à coup sûr une situation à éviter.

+2

il n'y a pas de diamant ici. Seul le nom est en conflit. A et B pourraient provenir de différentes bibliothèques. –

+0

@Alex oui, c'était une mauvaise terminologie, l'espace de noms est approprié. – jdehaan

+1

Comment la dérivation virtuelle aiderait-elle ici? – curiousguy

2

Pour contourner ce problème, essayez

struct Impl_A : A 
{ 
    void Function() { cout << "A::Function" << endl; } 
}; 


struct Impl_B : B 
{ 
    void Function() { cout << "B::function" << endl; } 
}; 

struct Impl : Impl_A, Impl_B {}; 
1

je peux suggérer une autre façon de résoudre ce problème. Vous pouvez ajouter un wrapper Typed qui modifie la signature Function en ajoutant un paramètre factice. Ainsi, vous pouvez distinguer les méthodes dans votre implémentation.

class A { 
public: 
    virtual void Function() = 0; 
    virtual ~A() = default; 
}; 

class B { 
public: 
    virtual void Function() = 0; 
    virtual ~B() = default; 
}; 

template<typename T> 
class Typed : public T { 
public: 
    virtual void Function(T* dummy) = 0; 
    void Function() override { 
    Function(nullptr); 
    } 
}; 

class Impl : public Typed<A>, public Typed<B> { 
public: 
    void Function(A* dummy) override { 
    std::cerr << "implements A::Function()" << std::endl; 
    } 
    void Function(B* dummy) override { 
    std::cerr << "implements B::Function()" << std::endl; 
    } 
}; 

L'avantage d'une telle solution est que toutes les implémentations sont placées dans une classe.

Questions connexes