Abstract classes & inheritance ORM support

Forum for posting problems using QxOrm library

Abstract classes & inheritance ORM support

Postby guparan » Wed May 11, 2011 7:40 am

Hi,

In order to integrate QxOrm in my project (using MYSQL database), I played for a while with your basic example "Drug".
My project uses abstract classes & inheritance, so I wanted to test class construction from database in this case with the example.

I wrote this code :

Drug.hpp
Code: Select all
#ifndef DRUG_HPP
#define DRUG_HPP

class QX_PROJECT_DLL_EXPORT Drug
{
public:

   long id;

   virtual void test() = 0;

   Drug() : id(0) { ; }
   virtual ~Drug() { ; }

};

QX_REGISTER_HPP_QX_PROJECT(Drug, qx::trait::no_base_class_defined, 0)

#endif // DRUG_HPP


Drug.cpp
Code: Select all
#include "precompiled.h"   // Precompiled-header with '#include <QxOrm.h>' and '#include "export.h"'
#include "Drug.hpp"        // Class definition 'Drug'
#include <QxMemLeak.h>     // Automatic memory leak detection

QX_REGISTER_CPP_QX_PROJECT(Drug)   // This macro is necessary to register 'Drug' class in QxOrm context

namespace qx {
template <> void register_class(QxClass<Drug> & t)
{
    t.id(& Drug::id, "IdFamConsignes"); // Register 'Drug::id' <=> primary key in my database
}}


Son.hpp
Code: Select all
#include "Drug.hpp"

#ifndef SON_HPP
#define SON_HPP

class QX_PROJECT_DLL_EXPORT Son : public Drug
{
public:
    QString name;
    QString designation;
    float montant;

    Son() {}
    void test () { ; }

};

QX_REGISTER_HPP_QX_PROJECT(Son, Drug, 0)

#endif // SON_HPP


Son.cpp
Code: Select all
#include "precompiled.h"   // Precompiled-header with '#include <QxOrm.h>' and '#include "export.h"'
#include "Son.hpp"         // Class definition 'Son'
#include <QxMemLeak.h>     // Automatic memory leak detection

QX_REGISTER_CPP_QX_PROJECT(Son)   // This macro is necessary to register 'drug' class in QxOrm context

namespace qx {
template <> void register_class(QxClass<Son> & t)
{
    t.setName("FamConsignes");

    t.data(& Son::designation, "Designation");       // Register 'Son::designation' property with key 'Designation'
    t.data(& Son::montant, "Montant");               // Register 'Son::montant' property with key 'Montant'
}}


main.cpp
Code: Select all
#include "precompiled.h"
#include "Drug.hpp"
#include "Son.hpp"
#include <QxMemLeak.h>

int main(int argc, char * argv[])
{
   // Init parameters to communicate with my database
   qx::QxSqlDatabase::getSingleton()->setDriverName("QMYSQL");
   qx::QxSqlDatabase::getSingleton()->setDatabaseName("db_edm");
   qx::QxSqlDatabase::getSingleton()->setHostName("localhost");
   qx::QxSqlDatabase::getSingleton()->setUserName("root");
   qx::QxSqlDatabase::getSingleton()->setPassword("");

   typedef boost::shared_ptr<Son> Son_ptr;
   Son_ptr p;
   p.reset(new Son());
   p->id = 1;

   QSqlError daoError = qx::dao::fetch_by_id(p);

   std::cout << "Id = " << p->id << std::endl;
   std::cout << "Famille = " << p->designation.toStdString() << std::endl;
   std::cout << "Montant = " << p->montant << std::endl;

   return 0;
}


But using abstract class Drug, compilation returns this error :
Code: Select all
error: cannot allocate an object of abstract type ‘Drug’
because the following virtual functions are pure within ‘Drug’:
virtual void Drug::test()



I can "disconnect" Drug from database (erasing macros and register_class method), add Id in all my Sons register_class method and change macro
QX_REGISTER_HPP_QX_PROJECT(Son, Drug, 0) for
QX_REGISTER_HPP_QX_PROJECT(Son, qx::trait::no_base_class_defined, 0) but isn't there any other solution ?
guparan
 

Re: Abstract classes & inheritance ORM support

Postby QxOrm admin » Wed May 11, 2011 8:28 am

Hi,

I reproduce your problem using "qxDllSample" project in "./test/" directory of QxOrm package and adding "virtual void test() = 0;" abstract method in "BaseClassTrigger" class.
I add also "virtual void test() { ; }" in "Foo" class and "Bar" class.
===> So "BaseClassTrigger" becomes an abstract class and "Foo" class and "Bar" class inherit from "BaseClassTrigger" class (this is the same case as you).

You are right : by default, there is an error.

You have to specialize a boost::serialization template.
I can build and execute project if I had following template specialization :

In "BaseClassTrigger.h" file, just before "QX_REGISTER_HPP_QX_DLL2(BaseClassTrigger, qx::trait::no_base_class_defined, 0)" line, add :
Code: Select all
namespace boost { namespace serialization {
template<> static void access::construct(BaseClassTrigger * t);
} } // namespace boost::serialization


In "BaseClassTrigger.qx.cpp" file, add the following implementation :
Code: Select all
namespace boost { namespace serialization {
template<> static void access::construct(BaseClassTrigger * t) { Q_UNUSED(t); }
} } // namespace boost::serialization


It works for me with Visual Studio C++ 2008 on Windows.
I don't know if it works with GCC or other compilers.


I think I will add a QX macro in the next version of QxOrm library with this code to manage abstract class inheritance...
QxOrm admin
 

Re: Abstract classes & inheritance ORM support

Postby guparan » Wed May 11, 2011 9:12 am

I tried your solution in my little example with GCC.

It didn't work, the error was :
Code: Select all
error: cannot declare member function ‘static void boost::serialization::access::construct(T*) [with T = Drug]’ to have static linkage
error: explicit template specialization cannot have a storage class


I tried then without the static keywords, it worked fine.
guparan
 

Re: Abstract classes & inheritance ORM support

Postby QxOrm admin » Wed May 11, 2011 10:01 am

Ok thanks, so the macro for abstract classes in the next version will work with VC++ and GCC.
Cool :)
QxOrm admin
 

Re: Abstract classes & inheritance ORM support

Postby guparan » Wed May 11, 2011 12:31 pm

Thank you for your work and your help ;)
guparan
 


Return to QxOrm - Help

Who is online

Users browsing this forum: No registered users and 6 guests

cron