Ho un codice legacy che, invece di funzioni virtuali, utilizza un campo kind
per eseguire l'invio dinamico. Sembra qualcosa di simile:Invio dinamico C++ senza funzioni virtuali
// Base struct shared by all subtypes
// Plain-old data; can't use virtual functions
struct POD
{
int kind;
int GetFoo();
int GetBar();
int GetBaz();
int GetXyzzy();
};
enum Kind { Kind_Derived1, Kind_Derived2, Kind_Derived3 /* , ... */ };
struct Derived1: POD
{
Derived1(): kind(Kind_Derived1) {}
int GetFoo();
int GetBar();
int GetBaz();
int GetXyzzy();
// ... plus other type-specific data and function members ...
};
struct Derived2: POD
{
Derived2(): kind(Kind_Derived2) {}
int GetFoo();
int GetBar();
int GetBaz();
int GetXyzzy();
// ... plus other type-specific data and function members ...
};
struct Derived3: POD
{
Derived3(): kind(Kind_Derived3) {}
int GetFoo();
int GetBar();
int GetBaz();
int GetXyzzy();
// ... plus other type-specific data and function members ...
};
// ... and so on for other derived classes ...
e poi i membri di funzione della classe POD
sono implementati in questo modo:
int POD::GetFoo()
{
// Call kind-specific function
switch (kind)
{
case Kind_Derived1:
{
Derived1 *pDerived1 = static_cast<Derived1*>(this);
return pDerived1->GetFoo();
}
case Kind_Derived2:
{
Derived2 *pDerived2 = static_cast<Derived2*>(this);
return pDerived2->GetFoo();
}
case Kind_Derived3:
{
Derived3 *pDerived3 = static_cast<Derived3*>(this);
return pDerived3->GetFoo();
}
// ... and so on for other derived classes ...
default:
throw UnknownKindException(kind, "GetFoo");
}
}
POD::GetBar()
, POD::GetBaz()
, POD::GetXyzzy()
, e gli altri membri sono implementate in modo simile.
Questo esempio è semplificato. Il codice attuale ha una dozzina di sottotipi diversi di POD
e un paio di dozzine di metodi. Nuovi sottotipi di e nuovi metodi vengono aggiunti abbastanza frequentemente, quindi ogni volta che lo facciamo, dobbiamo aggiornare tutte queste dichiarazioni switch
.
Il modo tipico per gestirlo sarebbe quello di dichiarare i membri della funzione virtual
nella classe POD
, ma non possiamo farlo perché gli oggetti si trovano nella memoria condivisa. C'è un sacco di codice che dipende dal fatto che queste strutture siano semplici vecchi dati, quindi anche se potessi immaginare un modo per avere funzioni virtuali in oggetti a memoria condivisa, non vorrei farlo.
Quindi, sto cercando suggerimenti sul modo migliore per pulire questo in modo che tutta la conoscenza di come chiamare i metodi di sottotipo sia centralizzata in un posto, piuttosto che sparsi in una dozzina di dozzine di switch
affermazioni in un una dozzina di funzioni.
Quello che succede a me è che posso creare una sorta di classe adattatore che avvolge un POD
e utilizza modelli per ridurre al minimo la ridondanza. Ma prima di iniziare questo percorso, mi piacerebbe sapere come gli altri hanno affrontato questo.
Lei ha detto che c'era un sacco di codice a seconda di questa classe. Puoi aggiungere dei campi o la struttura deve rimanere uguale? –
La struttura dovrebbe rimanere sostanzialmente la stessa. Abbiamo un sacco di enormi array di queste cose nella memoria condivisa, e stanno già andando a sbattere contro i limiti delle dimensioni della memoria. –
tutti i processi multipli hanno la stessa versione della libreria o no? –