Domanda Risolto Static library interfacce C++

Stato
Discussione chiusa ad ulteriori risposte.
Quello che vorrei fare e' linkare Engine.lib solo con l'eseguibile principale e poi passare un puntatore alle altre librerie del progetto in fase di inizializzazione.

L'unica cosa che mi e' venuta in mente e' dichiarare un "interfaccia" come classe astratta con metodi pure virtual "IMyClass".

E quindi passando alle altre lib/dll un puntatore a IMyClass e loro potrebbero usarla avendo solo il file header. Esiste un altro modo? Perche' questa classe espone attualmente 70 metodi pubblici, potrebbero aumentare e questo approccio e' incline ad errori, magari aggiorno la classe (sia aggiundendo/togliendo un metodo o cambiandone la signature) e dimentico di aggiornare l'interfaccia ecc.
Mi sembra proprio la soluzione giusta, tanto l'interfaccia verrebbe implementata anche da MyClass. Per la rimozione di metodi e per il cambiamento di signature di metodi non c'è problema: se rimuovi/modifichi un metodo in MyClass senza rimuoverlo/modificarlo in IMyClass hai un errore in compilazione, se aggiungi un metodo in MyClass dimenticandoti di aggiungerlo in IMyClass ti ritroveresti un errore in compilazione quando provi ad usarlo in una libreria.

Quello che vorrei fare e' linkare Engine.lib solo con l'eseguibile principale e poi passare un puntatore alle altre librerie del progetto in fase di inizializzazione. Il problema e' che se linkassi Engine.lib a tutto il resto avrei delle ripetizioni inutili dato che le altre lib non devono instanziare una "MyClass" ma devono solo chiamare dei metodi al suo interno per cui non hanno bisogno di portarsi dietro l'implementazione anch'esse ma solo includere il file header.
Il dynamic dispatch ha un impatto sulle performance, le ripetizioni inutili hanno un impatto per un fattore N (numero di librerie statiche) sullo spazio occupato sul tuo hdd e di un fattore 1 (numero di librerie dinamiche) sull'hdd degli user. Potenzialmente nessuno di questi fattori è rilevante, finché non fai benchmark la latency data dalla virtual table è impercettibile e e ~10MB in più o in meno su qualche terabyte di storage non danno fastidio a nessuno, ma personalmente io non mi porrei nemmeno il problema e mi terrei queste "ripetizioni inutili" che servono a farmi andare più veloce.
 
  • Mi piace
Reazioni: 0xbro e JunkCoder

JunkCoder

Moderatore
5 Giugno 2020
1,682
25
1,494
603
Ultima modifica:
Ciao, sto lavorando ad un progetto cosi' strutturato:
  • Static library "Engine.lib"
  • Eseguibile principale
  • Dynamic library 1
  • Static library 1
  • ... Static library N
In Engine.lib ho un file header che definisce una classe "MyClass" che e' necessaria a tutti gli altri progetti della solution. L'implementazione si trova sempre in Engine.lib.
Quello che vorrei fare e' linkare Engine.lib solo con l'eseguibile principale e poi passare un puntatore alle altre librerie del progetto in fase di inizializzazione. Il problema e' che se linkassi Engine.lib a tutto il resto avrei delle ripetizioni inutili dato che le altre lib non devono instanziare una "MyClass" ma devono solo chiamare dei metodi al suo interno per cui non hanno bisogno di portarsi dietro l'implementazione anch'esse ma solo includere il file header.

Secondo voi qual e' il modo piu' elegante per farlo?
L'unica cosa che mi e' venuta in mente e' dichiarare un "interfaccia" come classe astratta con metodi pure virtual "IMyClass", una cosa del tipo:

C++:
class IMyClass
{
public:
    IMyClass() = default;
    virtual ~IMyClass() = default;

    virtual int Method1() = 0;
    virtual void Method2() = 0;
    // ...
};

class MyClass : public IMyClass
{
public:
    MyClass();

    int Method1() override;
    void Method2() override;
    //...
}

E quindi passando alle altre lib/dll un puntatore a IMyClass e loro potrebbero usarla avendo solo il file header. Esiste un altro modo? Perche' questa classe espone attualmente 70 metodi pubblici, potrebbero aumentare e questo approccio e' incline ad errori, magari aggiorno la classe (sia aggiundendo/togliendo un metodo o cambiandone la signature) e dimentico di aggiornare l'interfaccia ecc.
Non posso convertire Engine in dll. Deve essere necessariamente statico.
 
Per questo progetto e' importante contenere le dimensioni anche a discapito di un pochino di performance, e il fattore N delle lib statiche potrebbe essere anche 20 o 30. Proseguiro' quindi con il sistema delle interfacce, grazie Steve.
 
Stato
Discussione chiusa ad ulteriori risposte.