Domanda

Ho un array di classe personalizzata Studente oggetti.CourseStudent e ResearchStudent entrambi ereditano da Studente, e tutte le istanze degli Studenti sono l'uno o l'altro di questi.

Ho una funzione per passare attraverso la matrice, determinare il sottotipo di ogni Studente, e poi chiamare il sottotipo specifico di funzioni membro su di loro.

Il problema è, dato che queste funzioni non sono in sovraccarico, non si trovano nelle Studente, in modo che il compilatore si solleva un polverone.

Se ho un puntatore a Studente, c'è un modo per ottenere un puntatore a un sottotipo di quello Studente?Avrei bisogno di fare una sorta di falso in ghisa qui per aggirare l'errore in fase di compilazione?

È stato utile?

Soluzione

È necessario un cast dinamico:

Student * s = new ...;    // create student of some sort

if ( ResearchStudent * r = dynamic_cast<ReasearchStudent*>( s ) ) {
   r->ResFunc();
}
else if ( CourseStudent * c = dynamic_cast<CourseStudent*>( s ) ) {
   c->CourseFiunc();
}
else {
   throw "unknown student type";
}

Si noti che queste informazioni impieghi tipo gestito dal compilatore, a condizione che la classe ha almeno una funzione virtuale - se tutto il resto fallisce, rendono il distruttore virtuale (come deve essere in questo caso anway). Si dovrebbe sempre preferire questo approccio per mantenere le proprie informazioni di tipo.

Altri suggerimenti

La cosa migliore sarebbe quella di utilizzare le funzioni virtuali:

class Student
{
   // ...
   virtual void SpecificFunction() = 0; /* = 0 means it's abstract; it must be implemented by a subclass */
   // ...
};

class CourseStudent
{
    void SpecificFunction() { ... }
};

Poi si può fare:

Student *student;
student->SpecificFunction();

A (peggio) alternativo può essere utilizzato dynamic_cast:

Student *student;
CourseStudent *cs = dynamic_cast<CourseStudent *>(student);

if (cs) {
   /* student is a CourseStudent.. */
   cs->SpecificFunction();
}

Funzioni virtuali sono inappropriati, perché la sottoclasse membro funzioni specifiche per tali sottoclassi (per esempio il CourseStudent dispone di un elenco di unità, mentre un ResearchStudent non è, quindi, una getUnits() implementazione della funzione in ResearchStudent avrebbe alcun senso)

Ho avuto un po ' di leggere su statico e dinamico cast ( in cplusplus.com typecasting ), e in questo caso penso che una statica cast è più appropriato.

Il generale svantaggio di un static_cast è che non esegue alcun controllo a runtime per garantire che l'oggetto del cast di un sottotipo è infatti che il sottotipo e non di qualche altro.In questo caso, sono in particolare il controllo del tipo prima di eseguire il tipo (uso privato i dati membro in cui è impostato il costruttore della sottoclasse e non ha mutator), così come lungo come il mio controllo è buona, non dovrebbe essere alcun problema con un statici cast.Statico cast è più efficiente, poiché un cast dinamico richiede più di runtime di risorse per eseguire il tipo di controllo.

Dove non c'è alcuna possibilità di un membro non è il tipo previsto, statico fusione non sarebbe opportuno quindi vorrei andare per dinamica casting (questo è un incarico così una volta che è stato inviato il codice non devono essere mantenuti in modo che non c'è nessun rischio di qualcuno che pasticciano in seguito).

Questa è quasi certamente un caso per l'utilizzo di una funzione di membro virtuale pura nella classe base, quindi imperativo di classi derivate in cui si fa il vero lavoro.

È necessario static_cast per questo. Dal momento che queste funzioni non sono membri virtuali della classe base non è possibile chiamare tramite un puntatore puntatore-a-base-class. È necessario lanciare esplicitamente al tipo effettivo dell'oggetto.

Il problema di solito è meglio risolto con funzioni virtuali -. Non è necessario il tipo di oggetto il check-nel codice più, avrà meno codice e meno superficie per i bug

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top