Visualizzazione dei risultati da 1 a 9 su 9
  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826

    [c++]dll e virtual function

    ciao.
    Ho creato una dll che importo in un .exe.
    Il problema è che se dichiaro una classe con una funzione normale nella classe base o nella classe derivata tutto ok.
    Se invece utilizzo le funzioni virtuali nella dll e uso le classi base e derivate con le funzioni virtuali non entra nelle funzioni.

    Shodan tempo fa mi aveva consigliato di utilizzare una factory e non l'esportazione col dll_export/dll_import, ma non ho capito molto bene.

    Dovrebbe funzionare il polimorfismo con le dll?
    Non capisco perchè no!
    ci deve essere un altro motivo, o un altro errore nel mio codice?

    grazie.

  2. #2
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Cosa non ti é chiaro di quanto scritto qui?
    http://chadaustin.me/cppinterface.html

    Shodan tempo fa mi aveva consigliato di utilizzare una factory e non l'esportazione col dll_export/dll_import, ma non ho capito molto bene.
    Semplicemente il motivo è non rendere la DLL compiler dependent (utilizzabile cioé solo con un preciso compilatore).

    Se invece utilizzo le funzioni virtuali nella dll e uso le classi base e derivate con le funzioni virtuali non entra nelle funzioni.
    Cosa te lo fa pensare?
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  3. #3
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    grazie shodan, ho letto l'articolo grazie ma il problema mi sembra diverso:

    ho creato una classe CViewBase che implementa alcune funzionalità , tra cui GetActions
    codice:
    class CORE_ITEM CViewBase : public COpenObject
    {
    public:
    	CViewBase(void);
    	~CViewBase(void);
    	virtual void GetActions(QVector<itemActionCommand*>& pViewAction)= 0;//è un vector contente una serie di oggetti strutture itemActionCommand
    };
    typedef std::shared_ptr<CViewBase> ptrViewBase;
    
    }
    ho diverse classi deriate da CViewBase e vorrei implementare il polimorfismo su tutto l'albero di derivazione da CViewBase.

    CViewBase è una view, presenta dei dati ma contiene questa funzione:
    codice:
    virtual void GetActions(QVector<itemActionCommand*>& pViewAction)= 0;//è un
    ogni view derivata da CViewBase implementa la funzione GetActions che mi ritorna un array di oggetti command da inserire in un menu.
    In pratica vorrei che quando seleziono una view, automaticamente mi si aggiornano le azioni(in menu' o tasti della toolbar) che quella view puo compiere.

    specifico per capirci meglio(ma mi sono reso conto che ho spiegato un po male) che ho creato la CViewBase in un progetto dll CORE mentre le classi derivate sono sotto un progetto QT .exe e un altro progetto con interfaccia grafica in opengl .exe.

    La view generica deve essere in una dll comune ai due sottosistemi.

    Solo che quando richiama da una view derivata il metodo virtuale GetActions non entra nelle funzioni di nessuna delle due classi delle due gui.
    Se creo invece un metodo non virtuale nella classe base CViewBase entra , esegue e ritorna il vettore(ho provato sia un vettore stl che un vettore QT).

    questa è una delle classi derivate dalla view , eredita anche da qglwidget che è il widget opengl di qt(puo dare problemi l'eredità multipla?)
    codice:
    class CGlWidgetImage : public CViewBase, public QGLWidget
    {
    
    public:
    	CGlWidgetImage(ptrFactoryCommand ptrFactory, ptrModelQT ptrMod, ptrModel ptrGraphicsModel, ptrControllerQt ptrController, QGLFormat format);
    	void  GetActions(QVector<itemActionCommand*>& pVect);
    grazie.

  4. #4
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    ho trovato questa discussione:

    http://stackoverflow.com/questions/3...dlist-from-dll

    ma non ho capito il template pod a cosa serve, secondo te puo essere una soluzione?

  5. #5
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    devo precisare che lavoro in QT.
    sono riuscito ad isolare il problema, sinceramente tutto quello che ho detto non centra niente.
    direttamente se istanzio una classe CGlWidgetImage e metto il contenuto in una CViewBase, poi chiamo sulla CViewBase il metodo virtuale GetActions tutto funziona!
    codice:
    ptrGlWidgetImage ptrGlWidgetImage = std::shared_ptr<CGlWidgetImage>( new CGlWidgetImage(ptrFactory, ptrQModel, ptrModelG, ptrController, format)) ;
    	((CViewBase*)ptrGlWidgetImage.get())->GetActions(n);
    Il CGlWidgetImage è anche un widget opengl, sottoclasse di qwidget e si comporta effettivamente da widget.
    codice:
    ptrGlWidgetImage->GetActions(..;
    ora il problema è questo:cosi non funziona
    codice:
    //.h di pSub in lib qtGui
    void setWidget(QWidget *widget);
    .
    .
    QMdiSubWindow* pSub = new QMdiSubWindow();
    pSub->setWidget(ptrGlWidgetImage.get());
    ((CViewBase*)pSub->widget())->GetActions(n);//non entra nella funzione

    widget() ritorna il widget inserito con SetWidget , ma non so perchè non mi richiama piu il GetActions. forse perchè la classeptr ptrGlWidgetImage e è derivata da due classi ? e viewbase non centra niente con la classe widget di setWidget() , dato che widget() ritorna un QWidget.

    per capire puo essere giusta la mia spiegazione all' errore?
    grazie.

  6. #6
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Personalmente no, non in un ambito di portabilità almeno. Di fatto il tizio li sta legando la DLL al compilatore col quale è compilata. Se un giorno (che può essere anche il giorno dopo) tale DLL dovesse essere usata con un alro compilatore (Intel, CLang, MinGW etc...) dovrebbe come minimo ricompilarla. Ricorda sempre che lo standard garantisce le interfaccie (che a volte si aggiornano), ma non le implementazioni. Se la DLL utilizza le std::string provviste da una libreria tipo STLPort, tale implementazione é diversa da quella di Microsoft, Borland, Intel etc.

    Venendo a noi.
    Vorrei chiarire un punto: non sono contrario all'uso di dll_export/dll_import in stile Microsoft a prescindere. Se per te è più semplice fare così per me non è un problema. Solo che vedendo la cosa in una prospettiva ad ampio respiro, il fatto di legare la DLL a una singola versione del compilatore, personalmente lo trovo parecchio limitante e abbastanza contradittorio del fatto che una DLL dovrebbe essere indipendente dal compilatore.

    Per l'articolo.
    Non mi pare che il problema sia molto diverso da quello descritto li.
    La tua classe CViewBase può benissimo stare nella DLL, solo che si chiamerà CViewBaseImpl.
    All'esterno avrai una classe Interfaccia (ICViewBase ?) completamente astratta che punterà a una implementazione diversa in base a ciò che ti serve.
    codice:
    // lato client.
    class ICViewBase : public COpenObject {
        public:
            virtual void GetActions(QVector<itemActionCommand*>& pViewAction)= 0;
            virtual void release()=0; // per liberare la memoria lato DLL
    };
    
    ICViewBase* metodo_factory(param); // spiego dopo
    
    // lato DLL
    class CViewBase : ICViewBase {
        public:
            ~virtual CViewBase() {} // può sempre servire.
            void GetActions(QVector<itemActionCommand*>& pViewAction) {
                /* qualcosa */
            }
            void release() { delete this; }
    };
    Ora però hai un altro problema: il metodo GetActions() accetta solo dei QVector. Se per qualche ragione ti servisse che so, una QList oppure un vector o list STL, saresti costretto a scrivere altrettanti metodi. Ho detto che i tipi STL è bene non passarli o riceverli come parametri, ma personalmente diffiderei anche dei QT. Il framework è sempre aggiornato è non so se è garantita la compatibilità binaria.
    Personalmente io userei una classe interfaccia da passare come parametro:
    codice:
    class ICommand {
        public:
        virtual ~ICommand() {} // sempre utile
        // inserisce un singolo elemento alla volta
        virtual void push_back(itemActionCommand* item)=0;
    };
    
    template <class Container>
    class CommandStore : public ICommand {
        Container& storage;
        public:
            CommandStore(Container& p) : storage(p) {}
            // inserisce un singolo elemento alla volta
            void push_back_once(itemActionCommand* item) {
                // 1) attenzione qui.
                storage.push_back(item);
            }        
    };
    ...
    
    ICViewBase* cvb = metodo_factory(request CGlWidgetImage);
    // Può anche essere una QList o un std::vector, std::list.
    QVector<itemActionCommand*> qv;
    CommandStore<QVector<itemActionCommand*>> cmdStore(qv);
    cvb->GetActions(&cmdStore);
    // si usa qv;
    ...
    // quando serve
    cvb->release();
    Ovviamente il metodo GetActions() di ICViewBase deve prendere un ICommand* come parametro.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  7. #7
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Parte II

    // 1) attenzione qui.
    Quel itemActionCommand* è un pò ambiguo, nel senso che non hai specificato se la sua allocazione avviene nella DLL oppure dal lato Client. Presumo quindi che sia il primo caso.
    Anche li il problema è che non puoi allocare nella DLL e deallocare dal lato client, anche li comunque puoi usare un metodo release() come nel caso della ICViewBase. Tuttavia anche itemActionCommand dev'essere una classe interfaccia o quanto meno una classe di cui sei sicuro che la sua implementazione sia stabile.

    (puo dare problemi l'eredità multipla?)
    A me non ne mai dati lato DLL.

    *EDIT*
    sinceramente tutto quello che ho detto non centra niente


    *RIEDIT*
    forse perchè la classeptr ptrGlWidgetImage e è derivata da due classi?
    No.
    e viewbase non centra niente con la classe widget di setWidget() , dato che widget() ritorna un QWidget.
    Ecco. Se QWidget non eredita da CViewBase, il polimorfismo te lo scordi. Anzi, forse sei già fortunato a non avere un crash.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  8. #8
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    codice:
    Ecco. Se QWidget non eredita da CViewBase, il polimorfismo te lo scordi. Anzi, forse sei già fortunato a non avere un crash.
    infatti è questo il problema .
    grazie comunque per il bel post.
    ciao.

  9. #9
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826

    [c++]Ereditarietà multipla

    tempo fa ho letto un articolo che parlava dei "pericoli" dell'ereditarietà multipla ma che sembravano ridimensionati da altri libri come c++ programming language di cui adesso rileggero quella parte.

    Io dopo che ho letto quell articolo(ma che avevo giudicato attendibile) , di cui purtroppo non mi ricordo il link per "sicurezza" ho risolto cercando di non usarla mai.
    ma a volte mi ci scontro come nel post ed è un casino.

    nella programmazione con le interfacce è normale utilizzare l'ereditarietà multipla in linguaggi come c#, anche se li viene fatta una distinzione tra ereditarietà e implementazione , infatti in questi linguaggi (anche java o php) uno puo' ereditare solo da una classe ma puo implementare il numero di interfacce che vuole.
    Ecco, l'implementazione in c++ non esiste , ma esiste l'ereditarietà multipla e se creo delle classi astratte pure
    codice:
    virtual void funzione() = 0;
    che secondo me assomigliano tanto alle interfacce , l'ereditarietà multipla non è da evitare come la peste , anzi bisogna usarla? penso di si.

    ma ritornando al post,una funzione virtuale(perchè sia polimorfica) deve essere implementata da tutte e due( o piu') le classi da cui derivo?
    e posso risolvere ereditando dalla classe che non l'implementa , implementarla in questa classe derivata ed ereditare da questa?
    perchè nei linguaggi come c# o java non esiste neanche questa possibilità(ereditarietà multipla) e perchè è stata fatta questa distinzione?(ereditarietà / implementazione)?

    insomma c'ho un po di casino sull ereditarietà multipla ma non solo dal classico esempio di due funzioni con nome uguale.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.