7

supponiamo po 'di codice (legacy), che non può essere toccato, dichiarareutilizzando sorella eredità

struct B{ 
public: 
    void f(){} 
}; 

e supponiamo di avere

struct A{ 
public: 
    virtual void f()=0; 
}; 

è possibile fare una Una chiamata sottoclasse B :: f senza chiamare esplicitamente f(), vale a dire invece di

struct C: public A, public B{ 
    void f(){ 
    B::f(); 
    } 
}; 

avere qualcosa di simile

0.123.
struct C:virtual public A,virtual public B{ 

}; 

(si noti che questa ultima classe è astratta, per il compilatore A :: F non è definito)

+2

Cosa c'è che non va con 'B :: f()'? Questo è il modo corretto per chiamare 'B :: f()'. –

+0

immagina di avere 100 funzioni;) –

+2

No, non è possibile che le funzioni dei membri di base possano * implementare * pure funzioni virtuali per un'altra classe base. Questo non funziona. Quello che hai va bene –

risposta

1

Direttamente in C++, è impossibile eseguire il mapping polimorfico in base ad alcune corrispondenze implicite delle funzioni di B in A. Potresti ricorrere ad un qualche tipo di generazione di codice usando gccxml o altri prodotti simili, ma se ci sono solo un centinaio di funzioni una macro può ridurre l'inoltro a una sola linea in ogni caso - non vale la pena di introdurre strumenti extra a meno che tu non abbia migliaia e migliaia di questi da fare

+0

"_dispatch polimorficamente basato su una corrispondenza implicita delle funzioni di B con A's_" G ++ _used_ per supportare le cosiddette "firme": [Digitare Abstraction using Signatures] (http://gcc.gnu.org/onlinedocs/gcc-2.95 .3/gcc_5.html # SEC112) "In GNU C++, è possibile utilizzare la firma della parola chiave per definire un'interfaccia di classe completamente astratta come un tipo di dati.È possibile connettere questa astrazione con le classi effettive usando i puntatori di firma. (...) Sottotipo diventa indipendente dall'eredità. (...) Le firme consentono di lavorare con le gerarchie di classi esistenti come implementazioni di un tipo di firma. " – curiousguy

+0

@curiousguy: questo è di interesse generale (rimozione data storica in gcc 3), ma non vedo come sia stato utile per fare ciò che la domanda cerca o più in generale il "dispatch polimorficamente basato su alcune corrispondenze implicite delle funzioni di B a A "citi. Dato 'firma S {void f(); }; ... S * p = static_cast (questo); p-> f(); 'sembra funzionalmente equivalente a dire' std :: function x = std :: bind (& B :: f, this); x(); '- entrambi sembrano più goffi di una semplice chiamata' B :: f(); 'come nella domanda. Non sono sicuro che mi manchi qualcosa ...? –

0

Si potrebbe fare qualcosa di simile:

void C::f() { 
    B* b = this; 
    b->f(); 
} 
+0

grazie, ma non voglio scrivere l'implementazione di ogni funzione (inoltre, qual è il vantaggio di questa versione rispetto a quello che ho scritto?) –

+0

@FabioDallaLibera: non capisco. Se non vuoi scrivere una funzione chiamata 'f' in' C', allora perché stai dichiarando tale funzione? Non c'è differenza tra questa implementazione di 'C :: f' e la tua in questo caso diversa da questa non si usa' B :: f' che si voleva evitare. –

0

No, non si può fare quella. E dal frammento che ci hai mostrato sembra che B debba essere un membro di C per composizione piuttosto che per ereditarietà. Dovrai solo scrivere alcune funzioni di inoltro (o uno script per generarle automaticamente).

1

Fai un'implementazione A che delega al B:

class A_Impl : public A 
{ 
public: 
    virtual void f() 
    { 
     b.f(); 
    } 
private: 
    B b; 
} 

Implementare C derivando da A_Impl:

class C: public A_Impl 
{ 
}; 

Oppure, se solo si desidera mostrare A nella gerarchia di ereditarietà, derivano pubblicamente da A e privatamente da A_Impl:

class C: public A, private virtual A_Impl 
{ 
}; 
-1

Quindi, hai 100 funzioni virtuali pure in A, implementazioni di quelle funzioni in B, e vuoi evitare di scrivere ri-implementare tutte quelle funzioni in C per chiamare B. Non c'è modo di usare il compilatore L'implementazione di B è automaticamente. Invece di combattere con il compilatore (perderai ogni volta!), ripensa il grafico di ereditarietà. Forse fare B una sottoclasse di A e poi derivare C da B. o il fattore i 100 metodi fuori di B e in una sottoclasse concreta di A.

La programmazione è l'arte di risolvere i problemi all'interno dei vincoli previsti dai vostri strumenti. Quando ti trovi in ​​disaccordo con i tuoi strumenti, devi riconsiderare il tuo approccio al problema o utilizzare strumenti diversi.

+0

La domanda dice che B non può essere toccato, quindi non puoi renderlo una sottoclasse di A, e non puoi spostare metodi da esso. – Karu