У меня есть два класса 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
ошибка.
Ниже приведена схема установки и некоторая информация о том, как реализованы классы:
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();
}