Funzioni membro vs. Funzioni non membri per operatori matematici

12

Sto scrivendo una libreria algebra lineare (per farla breve, è un compito scolastico) che coinvolge matrici, vettori, ecc. Nel processo di creazione di questa libreria, creerò funzioni che eseguono operazioni matematiche su oggetti. Ad esempio, trasponi matrice, inverti matrice, normalizza vettore, ecc.

Ero curioso di sapere quale sia la "migliore pratica" per questo tipo di funzione ... Cioè, dovrei rendere la funzione una funzione membro o non membro? (Per chiarezza / biblioteca usa il sake)

Esempio:

//Member function way:
B = A.transpose();
C = A.inverse();

//Non-member function way:
B = linalg::transpose(A); //Non-member transpose function in linear algebra namespace
C = linalg::inverse(A);

Esistono standard per questo tipo di operazioni? O, almeno, c'è un modo comune di farlo? Mi sto appoggiando alla prima opzione, ma mi piacerebbe sapere se è consigliabile.

    
posta apnorton 22.02.2014 - 04:36
fonte

4 risposte

7

Questa è solo una questione di stile e gusto. Ho visto diverse librerie di algebra lineare,

  • scritto in uno stile OOP utilizzando le funzioni membro

  • scritto in uno stile non OOP utilizzando solo funzioni libere

  • fornendo un'API con entrambi

e tutti loro stavano lavorando. Almeno, la tua API deve essere coerente, quindi scegli la tua scelta e assicurati di non mescolare questi stili in modo arbitrario.

    
risposta data 22.02.2014 - 11:33
fonte
8

Avoid membership fees: Where possible, prefer making functions nonmember nonfriends.

Nonmember nonfriend functions improve encapsulation by minimizing dependencies: The body of the function cannot come to depend on the nonpublic members of the class (see Item 11). They also break apart monolithic classes to liberate separable functionality, further reducing coupling (see Item 33). They improve genericity, because it's hard to write templates that don't know whether or not an operation is a member for a given type [...]

Herb Sutter

    
risposta data 31.12.2015 - 07:59
fonte
1

Entrambe le funzioni membro e non membro hanno vantaggi reali oltre al semplice gusto. Ad esempio, gli array sottostanti utilizzati per implementare una classe matrix saranno probabilmente private , quindi, dovrai utilizzare friend a meno che non usi le funzioni membro. In questo senso, un design OO potrebbe essere migliore.

Tuttavia, tieni presente che, di volta in volta, gli informatici devono implementare una formula matematica complessa senza sapere sempre cosa realmente fanno. Quando devo farlo, preferisco le funzioni non membro poiché il risultato "visivo" sarà più vicino alla formula matematica originale (poiché la formula matematica generalmente usa uno stile funzionale).

Alla fine, la risposta è la stessa di Doc Brown: è una questione di gusti. In breve, potresti prendere in considerazione la scrittura di una libreria in stile OO con funzioni membro (più facile scrivere, nessuna friend ), quindi scrivere funzioni non membro per svolgere le stesse attività che semplicemente inoltreranno i loro argomenti a quelle dei membri. Ti consente di essere coerente e di consentire all'utente di scegliere ciò che pensa sia il migliore.

    
risposta data 25.02.2014 - 12:10
fonte
0

Se ti immergi più in profondità nell'affermazione del problema, è chiaro che ad un certo punto utilizzerai strutture dati personalizzate che rappresentano determinate entità matematiche. Ad esempio, potresti rappresentare una matrice come mezzo di una matrice n-dimensionale. Per elaborare il tuo esempio,

// C way
typedef struct {
    int data[MAX_LEN][MAX_LEN];
} MATRIX;

MATRIX B = transpose(A);

// C++ way
class Matrix; // Forward Declaration
class Matrix {
    int data[MAX_LEN][MAX_LEN];
    public:
        Matrix transpose();
};

Matrix B = A.transpose();

(L'esempio di C ++ è semplificato, puoi usare template e così via.)

Il punto da considerare è la facilità di utilizzare strutture dati personalizzate in entrambi i casi. Il C ++ (o qualsiasi oggetto orientato agli oggetti) come linguaggio è più potente di per sé, e si estende al consumatore della biblioteca tanto quanto ne beneficia l'implementatore. Ho usato solo le librerie C in passato e quelle strutture dati personalizzate sembrano arrivare dappertutto in pochissimo tempo! Considerando che l'interoperabilità è più facile da raggiungere con quest'ultimo (utilizzando costruttori speciali, forse?)

Per riavvolgerlo, se stai usando il C ++, è assolutamente consigliato un approccio orientato agli oggetti.

    
risposta data 22.02.2014 - 15:10
fonte

Leggi altre domande sui tag