E 'possibile in C ++ definire diversi metodi contemporaneamente?

4

Ci scusiamo per il titolo confuso di questa domanda, ma non riesco a pensare a un modo esatto per esprimerlo. Ho una lezione molto lunga con centinaia di metodi simili e sto cercando di trovare un modo per costruirlo senza così tante righe di codice e così tante violazioni DRY. Ogni volta che aggiungo una nuova proprietà alla mia classe, devo scrivere due metodi e aggiornare la funzione di copia. Ci sono già oltre 80 proprietà.

Attualmente questa classe è scritta in Java, ma mi chiedevo se fosse scritta in C ++ se potesse essere eseguita in modo più efficiente. Penso che si possa fare usando il preprocessore x-macros come descritto in wikipedia qui ma non sono un fan dei macro e vorrei preferisci farlo usando il linguaggio stesso, se possibile.

Ecco uno snippet semplificato della mia classe Java:

class InMemoryPerson implements Person {
    private HashMap<String,Object> values = new HashMap<String,Object>();

    public InMemoryPerson copyFrom(Person p) {
        setName(p.getName());
        // more code to copy all the properties...
    }

    public void setName(String name) {
        values.put("name",name);
    }

    public String getName() {
        return (String)map.get("name");
    }

    // many more methods for all the different properties...
    // each method may have a different type
}
    
posta satur9nine 02.05.2013 - 07:48
fonte

5 risposte

9

In C ++ è possibile farlo, usando macro C di vecchio stile.

// method is get/set method suffix
// name is the key in hash table
#define POINTER_PROPERTY(type,method,name) \
        type get##method(){return (type)_pointer_map[name];} \
        void set##method(type value){_pointer_map[name]=value;}

class InMemoryPerson : Person {
public:
    POINTER_PROPERTY(char *,Name,"name")

private:
    std::map<const char *,void *> _pointer_map;
};

I tipi di valore dovrebbero essere gestiti da diverse macro e (modo più semplice) da diversi hash per ogni tipo. Non sono sicuro che questo codice sia più leggibile e gestibile di 80 diverse funzioni get / set.

    
risposta data 02.05.2013 - 11:06
fonte
1

In c ++ dovrebbe essere abbastanza semplice. Eliminare setter e getter e variabili membro e utilizzare i costruttori di copia predefiniti per copiare oggetti di questa classe. Qualcosa del genere:

struct Person
{
    Person() : name("default name")
    {}

    std::string name;
    // etc
};

Person a;
// set fields of person a
Person b;
// set fields of person b
b = a;
    
risposta data 02.05.2013 - 08:04
fonte
1

Questa non è davvero una risposta a causa del seguente vincolo da un commento ...

Because I am implementing an interface this is not possible, there are several other implementations and my class must be compatible with the interface.

Tuttavia, potrebbe essere una risposta per qualcun altro, quindi ...

Un'opzione consiste nel fornire un getter e setter per ogni tipo e utilizzare un parametro per identificare quale proprietà. Posso pensare a due modi per gestire questo ...

  • Utilizza un enumerato per fornire tutti i nomi delle tue proprietà e memorizza tali proprietà in un array.

  • Utilizzare una struttura separata per definire tutti i dati dei membri, eventualmente come membri pubblici della classe. Archiviare le proprietà utilizzando in un'istanza privata di tale struttura all'interno della classe. Passa puntatori membri ai tuoi getter e setter per identificare la proprietà.

In entrambi i casi, i getter e i setter possono gestire particolari proprietà specialmente se necessario. Il metodo del puntatore del membro è solo menzionato per completezza, però - preferirei il metodo di enumerazione.

Una volta che puoi identificare quale proprietà usa un parametro, hai ancora bisogno di getter e setter diversi per ogni tipo di dati di proprietà. Questo può essere evitato specificando getter e setter come funzioni del modello membro. Sono comunque necessari alcuni controlli, per garantire che la proprietà per la chiamata corrente abbia il tipo corretto. Questo è in realtà più semplice se si utilizza l'approccio pointer del membro (il modello può richiedere che il tipo di membro per il puntatore del membro corrisponda al tipo get / set) anche se probabilmente si avranno altri problemi in seguito.

Il caso più ovvio in cui qualcosa di simile è giustificato è se stai sviluppando uno strumento in stile RAD.

    
risposta data 02.05.2013 - 13:56
fonte
0

La necessità di aggiornare la funzione di copia può essere evitata utilizzando i dispositivi di copiatura predefiniti, come indicato da @ BЈовић. Per getter e setter, tuttavia, vorrei mordere il proiettile e utilizzare X-macros (se non si desidera scrivere un generatore di codice esterno per questo).

Qualunque cosa tu faccia, hai bisogno di un posto dove associ la chiave hash "name" con il tipo di dati associato String e i corrispondenti nomi getter / setter (i nomi di questi metodi possono seguire una convenzione rigorosa, ma AFAIK lì non è una conversione maiuscola / minuscola facile all'interno del preprocessore). Quindi definire questo elenco usando X-macros ti darà almeno una soluzione molto compatta e facile da estendere (EDIT: vedi il messaggio di @ petrch per un esempio).

    
risposta data 02.05.2013 - 11:01
fonte
0

C'era una serie in tre parti su Embedded.com su X-macros, che fornisce un risultato più pulito di quello descritto nell'articolo di Wikipedia.

#define EXPAND_AS_ENUMERATION(a,b) a,
#define EXPAND_AS_JUMPTABLE(a,b) b, 
#define STATE_TABLE(ENTRY)     \
        ENTRY(STATE_0, func_0) \
        ENTRY(STATE_1, func_1) \
        ENTRY(STATE_2, func_2) \
        ...                    \
        ENTRY(STATE_X, func_X)

/* declare an enumeration of state codes */ 
enum{
    STATE_TABLE(EXPAND_AS_ENUMERATION)
    NUM_STATES
}

/* declare a table of function pointers */ 
p_func_t jumptable[NUM_STATES] = {
    STATE_TABLE(EXPAND_AS_JUMPTABLE)
}:

Ecco Parte 1 .

Ecco Parte 2 .

Hanno soffiato il link in-article alla Parte 3. Qui lo è.

Ti richiedono di creare un account e un profilo gratuiti, in modo che possano inviarti spam se desideri leggere più di 2 articoli al giorno. (BOO! HISS!) Il limite di 2 articoli è un cambiamento abbastanza recente rispetto a quello che era un sito veramente buono.

    
risposta data 02.05.2013 - 14:18
fonte

Leggi altre domande sui tag