Наилучшая практика: Инициализация различных параметров * stati c при инерции в разных классах - PullRequest
0 голосов
/ 03 марта 2020

У меня есть два класса Class A и Class B объектов, которые наследуются от Class C. Class C содержит stati c приватных параметров, которые я хотел бы инициализировать различными значениями в Class A и Class B. Class A и Class B на самом деле являются контейнерами, заполненными некоторыми математическими операциями. И Class B принимает элемент Class A в качестве аргумента в конструкторе.

Когда я инициализирую приватные параметры stati c для Class C в начале Class A и Class B, я получаю a multiple definition of C::m_paramC ошибка.

Ниже приведена схема установки и некоторая информация о том, как реализованы классы: enter image description here

AH

class A: public C
{
public:
    Type methodsA()
private:
    Type m_paramA;
}

A. CPP

#include "B.h"
#include "C.h"

Type C::m_paramC = something;

Type A::methodsA()
{
}

Аналогично для Class B без включения в B и параметра stati c от C должно быть с другим значением по сравнению с A Type C::m_paramC = something_else;.

C .H

class C
{
public:
Template<class T>
Type C::methodsC()
{
   /* use of m_paramC */
}
private:
    static Type m_paramC;
}

template<T> in C .H позволяет выполнять те же операции над объектами из A или B. Итак, мой вопрос заключается в следующем: как лучше объединить классы способом, описанным выше, и иметь возможность изменять в A и B значения частные параметры C?

На самом деле, я пытаюсь использовать m_param C в моих функциях stati c и в то же время мне нужно m_param C для изменения в зависимости от того, идет ли речь о объектах типа A или объектах типа B


РЕДАКТИРОВАТЬ. Ниже приведен минимальный пример, предложенный Тедом Люнгмо .

example.pro

QT -= gui
QT += sql

CONFIG += c++11 console
CONFIG -= app_bundle

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        a.cpp \
        b.cpp \
        c.cpp \
        main.cpp

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

HEADERS += \
    a.h \
    b.h \
    c.h

ах

#ifndef A_H
#define A_H

#include "QString"
#include "c.h"

class A: public C
{
public:
    A(const QString &, const double &);
    A();

    void setParamA(const double &);
    const double& getParamA() const;

    void setMemberId(const QString &);
    const QString& getMemberId() const;


private:
    QString m_memberId;
    double m_paramA;

    //**************************************************************//
    //***********************SERIALIZATION**************************//
    //**************************************************************//

    friend QDataStream &operator<<(QDataStream &out, const A &a)
    {
        out << a.getMemberId() << a.getParamA();
        return out;
    }

    friend QDataStream &operator>>(QDataStream &in, A &a)
    {
        QString memberId;
        double paramA;

        in >> memberId >> paramA;

        a.setMemberId(memberId);
        a.setParamA(paramA);

        return in;
    }


};

#endif // A_H

a. cpp

#include "a.h"

QString C::m_connectionName = "aDB";
QString C::m_pathDatabase = "dbA.db";


A::A(const QString &memberId, const double & param):
    m_memberId(memberId),
    m_paramA(param)
{

}

A::A()
{

}

void A::setParamA(const double &x)
{
    m_paramA = x;
}

const double & A::getParamA() const
{
    return m_paramA;
}

void A::setMemberId(const QString &x)
{
    m_memberId = x;
}

const QString & A::getMemberId() const
{
    return m_memberId;
}

чч

#ifndef B_H
#define B_H


#include "QString"
#include "a.h"
#include "c.h"

class B: public C
{
public:
    B(const QString &, const A &);
    B();

    void setParamB(const double &);
    const double& getParamB() const;

    void setMemberId(const QString &);
    const QString& getMemberId() const;


private:
    QString m_memberId;
    double m_paramB;


    //**************************************************************//
    //***********************SERIALIZATION**************************//
    //**************************************************************//

    friend QDataStream &operator<<(QDataStream &out, const B &b)
    {
        out << b.getMemberId() << b.getParamB();
        return out;
    }

    friend QDataStream &operator>>(QDataStream &in, B &b)
    {
        QString memberId;
        double paramB;

        in >> memberId >> paramB;

        b.setMemberId(memberId);
        b.setParamB(paramB);

        return in;
    }

};


#endif // B_H

б. cpp

#include "b.h"


/*
QString C::m_connectionName = "bDB";
QString C::m_pathDatabase = "dbB.db";
*/

//I want here to be able to connect to a different database but if I remove the comments, I have the famous error


B::B(const QString &memberId, const A & a):
    m_memberId(memberId),
    m_paramB(a.getParamA() / 2)
{

}

B::B()
{

}

void B::setParamB(const double &x)
{
    m_paramB = x;
}

const double & B::getParamB() const
{
    return m_paramB;
}

void B::setMemberId(const QString &x)
{
    m_memberId = x;
}

const QString & B::getMemberId() const
{
    return m_memberId;
}

c .ч

#ifndef C_H
#define C_H

#include "QString"
#include "QDebug"
#include "QtSql"

class C
{
public:
    C();
    static void initConnectionToDB();
    static void createNewTableInDB( const QString &);
    static QSqlDatabase connectToDB();
    static void closeConnectionToDB();

    template <class T>
    static QByteArray object2blob( const T& u )
    {
      QByteArray blob;
      QDataStream bWrite( &blob, QIODevice::WriteOnly );
      bWrite << u;
      return blob;
    }

    template <class T>
    static T blob2object( const QByteArray& blob, T& t)
    {
      QDataStream bRead( blob );
      bRead >> t;
      return t;
    }

    template <class T>
    static void saveToDB(const T& t, const QString & tableID, const QString & memberId)
    {
        QSqlQuery query(connectToDB());

        query.prepare( "INSERT INTO " + tableID + " (memberId,objectBlob) VALUES (:memberId,:objectBlob)" );
        query.bindValue(":memberId", memberId);
        query.bindValue(":objectBlob",  object2blob<T>(t) );
        if( !query.exec() )
        {
            qDebug() << query.lastError().text();
        }
    }

    template <class T>
    static T readFromDB(const QString & tableID, const QString & memberId )
    {
        QSqlQuery query(connectToDB());
        query.prepare( "SELECT * FROM " + tableID + " WHERE memberId ='"+ memberId +"'" );
        T t;
        if ( !query.exec() )
        {
            qDebug() << query.lastError().text();
        }
        else
        {
            if ( !query.next())
            {
                qDebug()<<"Not in the database";
            }
            else
            {
                t = blob2object<T>( query.value( 1 ).toByteArray(), t );
            }
        }
        return t;
    }

protected:
    static QString m_connectionName;
    static QString m_pathDatabase;

};

#endif // C_H

c. cpp

#include "c.h"

C::C()
{

}

void C::initConnectionToDB()
{
    QSqlDatabase myDB = QSqlDatabase::addDatabase("QSQLITE", QStringLiteral("%1").arg(m_connectionName));
    myDB.setDatabaseName(m_pathDatabase);
    if (!myDB.open())
    {
        qDebug()<<myDB.lastError().text();
    }
}

QSqlDatabase C::connectToDB()
{
    return QSqlDatabase::database(QStringLiteral("%1").arg(m_connectionName));
}

void C::closeConnectionToDB()
{
    QSqlDatabase::removeDatabase(QStringLiteral("%1").arg(m_connectionName));
}

void C::createNewTableInDB( const QString &tableId)
{
    QSqlQuery query(C::connectToDB());
    query.prepare( "CREATE TABLE IF NOT EXISTS " + tableId + " (memberId TEXT, objectBlob BLOB)" );
    if( !query.exec() )
    {
        qDebug() << query.lastError().text();
    }
}

main. cpp

#include <QCoreApplication>
#include "a.h"
#include "b.h"


int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    A::initConnectionToDB();
    B::initConnectionToDB();


    A::createNewTableInDB("testTableA");


    A a1("pA", 6);
    a1.saveToDB(a1,"testTableA", "memberA1");

    A a2 = A::readFromDB<A>("testTableA", "memberA1");
    qDebug()<<a2.getMemberId()<<a2.getParamA();



    B::createNewTableInDB("testTableB");


    B b1("memberB1",a1);
    b1.saveToDB(b1, "testTableB", "memberB1");


    A::closeConnectionToDB();
    B::closeConnectionToDB();

    return app.exec();
}
...