2010-06-30 18 views
18

que tienen algo por el estilo (simplificado)C++ o funciones de mando virtuales con el mismo nombre

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

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

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

¿Cómo puedo implementar la función() para A y de la función() para B? Visual C++ solo le permite definir la función específica en línea (es decir, no en el archivo cpp), , pero supongo que es una extensión. GCC se queja de esto. ¿Hay una forma estándar de C++ para decirle al compilador qué función quiero anular?

(Visual C++ 2008)

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

Gracias!

+0

Además, finalmente me he dado cuenta de cómo funciona QueryInterface cuando se implementan múltiples interfaces COM. :) – QbProg

Respuesta

30

No puede usar nombres calificados allí. Yo escribo void Function() { ... } está anulando ambas funciones. Herb Sutter muestra how it can be solved.

Otra opción es cambiar el nombre de esas funciones, porque aparentemente hacen algo diferente (de lo contrario, no veo el problema de anular ambos con un comportamiento idéntico).

+0

gracias por el enlace :) – QbProg

-1

Si A y B son interfaces, entonces usaría la derivación virtual para "unirlas" (hacer que se superpongan). Si necesita implementaciones diferentes para su Function si lo llama a través de un puntero a A o a B, le recomiendo encarecidamente que elija otro diseño. Eso duele de lo contrario.

Impl "deriva de" A y B significa Impl "es un" A y B. Supongo que no lo dices en serio.

Impl "implementa la interfaz" A y B significa Impl "se comporta como" A y B. entonces la misma interfaz debería significar el mismo comportamiento.

En ambos casos, tener un comportamiento diferente según el tipo de puntero utilizado sería "esquizofrénico" y es una situación segura de evitar.

+2

no hay diamantes aquí. Solo nombre clash. A y B podrían provenir de diferentes bibliotecas. –

+0

@Alex sí, era mala terminología, el espacio de nombres es apropiado. – jdehaan

+1

¿Cómo ayudaría la derivación virtual aquí? – curiousguy

2

Como solución, tratar

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

puedo sugerir otra manera de resolver este problema. Puede agregar el contenedor Typed que cambia la firma Function agregando el parámetro ficticio. Por lo tanto, puede distinguir los métodos en su implementación.

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; 
    } 
}; 

El beneficio de tal solución es que todas las implementaciones se ubican en una clase.

Cuestiones relacionadas