Qt multiple inheritance ambiguous base class - c++

So, my class hierarchy looks something like this:
QObject QGraphicsPolygonItem
\ /
\/
CBubble
/\
/ \
CListBubble CSingleLinkBubble
\ /
\/
CActionBubble
The reason I'm doing multiple inheritance is because I have another bubble that is a CListBubble (LB), but not a CSingleLinkBubble (SB).
The error I receive is "CBubble is an ambiguous base of CActionBubble".
I've tried the virtual tag on one or both of them.
I've tried adding "virtual CBubble" to CActionBubble.
I've tried changing to "public virtual CBubble" in LB and SB, but that causes issues in all bubbles that inherit from them.
I could forego CListBubble entirely and copy/pasta the code, but that goes against all my instincts. I could try to refactor this to use the decorator pattern, but that seems like a lot of unnecessary work for this one case.
Any help or suggestions are much appreciated.
Thanks.
EDIT:
I apologize, should have read the MCVE rules.
Note - I just typed this up now, so hopefully there aren't any syntax issues, but I assume it gets the point across.
clistbubble.h
// header guard
#include "cbubble.h"
class CListBubble : public CBubble
{
public:
CListBubble(const QPointF & pos, QGraphicsItem *parent = 0);
// data members/methods
};
clistbubble.cpp
#include "clistbubble.h"
CListBubble(const QPointF & pos, QGraphicsItem *parent)
: CBubble(pos, parent) // rest of base member initialization
{
// other stuff for this type of bubble
}
// Other methods
The header for CSingleLinkBubble is equivalent in all but members and methods.
cactionbubble.h
// header guard
#include "csinglelinkbubble.h"
#include "clistbubble.h"
class CActionBubble : public virtual CSingleLinkBubble, public virtual CListBubble
{
public:
CActionBubble(const QPointF & pos, QGraphicsItem *parent);
// data members/methods
};
cactionbubble.cpp
#include "cactionbubble.h"
CActionBubble(const QPointF & pos, QGraphicsItem *parent)
: CSingleLinkBubble(pos, parent), CListBubble(pos, parent) // rest of base member initialization
{
// other stuff for this type of bubble
}
I'm concerned that the issue lies in the constructor of CActionBubble where both parent classes are called. However both calls are necessary and would happen anyway if I implemented a default ctor.
The error points me to the place I attempt to new a CActionBubble.
"CBubble is an ambiguous base of CActionBubble"
I also forgot to mention that CBubble inherits from QObject so I can implement signals and slots. I read something awhile back that multiple inheritance with QObject is not possible. Could it be that this is the actual issue, and the error just points one layer below?

Related

Unreal engine Abstract class example c++

i have been looking for quite some time online for a good Abstract class (UCLASS(Abstract)) example but haven't came accross a good one yet.
Is there anyone with a good Link i can goto or Anyone who could show me a simple example, i would appreciate alot.
WeaponBase.h
UCLASS(Abstract, Blueprintable)
class FPS_API AWeaponBase : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AWeaponBase();
/** This will be used in sub classes */
UFUNCTION(BlueprintCallable, Category = "Functions")
virtual void OnFire(AFPSCharacter* Character);
}
Weapon_Assault.h
UCLASS()
class FPS_API AWeapon_Assault : public AWeaponBase
{
GENERATED_BODY()
public:
FVector spread;
AWeapon_Assault();
};
Weapon_Assault.cpp
#include "Weapon_Assault.h"
AWeapon_Assault::AWeapon_Assault()
{
AWeaponBase();
spread = FVector(0.5f, 0.0f, 100.0f);
}
// this function from abstract super class
void OnFire(AFPSCharacter* Character)
{
}
The original code is quite big so i don't want to post it here, but this is basically what it looks like, and i keep getting errors.
Also i can't even declare "OnFire" in main class and subclass at the same time?!
All class definitions must have ; after last } Like this:
UCLASS(Abstract)
class UAnimalBase : public UObject
{
GENERATED_BODY()
public:
UAnimalBase(const FObjectInitializer& ObjectInitializer);
};
You need to add a declaration of an overridden function to your Weapon_Assault.h
UCLASS()
class FPS_API AWeapon_Assault : public AWeaponBase
{
GENERATED_BODY()
public:
FVector Spread;
AWeapon_Assault();
virtual void OnFire(AFPSCharacter* Character) override; // THIS ONE
};
Note that you don't need UFUNCTION() specifier above the overridden function, only on the first declaration.
AWeapon_Assault::AWeapon_Assault() also has a mistake. You don't call constructors of parent classes in C++ they will be called automatically.
AWeapon_Assault::AWeapon_Assault()
{
// AWeaponBase(); THIS LINE IS WRONG
Spread = FVector(0.5f, 0.0f, 100.0f);
}
Create a definition for your functions in the abstract class (they can stay empty). Yes, it doesn't make sense though it does. Abstract is a specifier only inside of UnrealEngine but code still needs to be compiled with C++ standards. The absence of these definitions will cause compile errors.
We use UpperCamelCase or PascalCase in Unreal Coding Standart which is nice to have. But that one is not necessary.
So your variable should be FVector Spread; Also you probably shall wrap it with UPROPERTY() macro but that's a different topic.

Use of temporal constructors inside vector

I cam from programming in Java and I thought doing as here [my code] could work the definition of temporal constructors, but I am having problems the proper way of writing the code to just work.
PROBLEM: I want to add a Constructor of the class Coomunication for every port I find in a machine and save it into a vector:
ControlCommunication.cpp:
...
QVector<Comunication *> ports;
...
void ControlCommunication::checkPorts(){
qint16 vendorid = cuquito.getVendorID();
qint16 productid = cuquito.getProductID();
const QString blankString = "N/A";
for (const QSerialPortInfo &serialPortInfo : QSerialPortInfo::availablePorts()) {
Comunication com(serialPortInfo.portName());
addPort(com); // <- I do not know how to get this working well
}
}
ControlCommunication.h:
class ControlCommunication : public QObject
{
Q_OBJECT
public:
explicit ControlCommunication(QObject *parent = nullptr);
QVector<Comunication*> getComunicationPorts(){return comunicationports;}
void addPort(Comunication com);
...
Comunication.h:
#ifndef COMUNICATION_H
#define COMUNICATION_H
#include <QObject>
#include <QSerialPort>
#include <QMainWindow>
class Comunication:public QObject{
Q_OBJECT
public:
Comunication( QString serialPortName);
Comunication();
public:
public slots:
void openSerialPort();
void closeSerialPort();
void writeData(const QByteArray &data);
void readData(QByteArray &data);
void handleError(QSerialPort::SerialPortError error);
QString getPortName(){return portname;};
signals:
private:
QSerialPort *m_serial = nullptr;
QString portname;
};
#endif // COMUNICATION_H
The error I get is: call to implicitly-deleted copy constructor of 'Comunication'
comunication.h:8:20: note: copy constructor of 'Comunication' is implicitly deleted because base class 'QObject' has a deleted copy constructor
qobject.h:449:20: note: 'QObject' has been explicitly marked deleted here
controlcommunication.cpp:27:49: note: passing argument to parameter 'com' here
As I understand from the error message, I cannot call a constructor which is gonna be deleted in that function from other statements. How can i get this working?
The error you're getting mean you can't copy Communication. When you're passing com to addPort, you're making a copy of the object which will be passed to the function. But because you're inheriting a QObject you can't make copies of your objects. Which means you can't those objects by value. You can add pointers or (ideally) a reference to use objects.
But in your case, I don't think that's going to work easily, you seem to want a QVector<Communication*> which I'm assuming will be filled by addPort. But you're creating Communication in your loop which will be delted when it exists the loop, and so pointers to it won't work.
I don't have enough information, and I'm not versed with Qt, so please someone correct if I'm wrong, but I would suggest that you build Communication inside addPort and change QVector<Communication*> to QVector<Communication>.
My intuition would be that Communication doesn't need to inherit from QObject, but I could be wrong. But the data from your program should probably be separated from the Qt stuff, to make things easier to manage.
You are passing the Comunication object by value into the addPort function. This will try to create a copy of the object. But QObjects (and anything derived from QObject) are non-copyable. So you should change your function to take a pointer or reference instead.
Also, you probably need to allocate your objects on the heap because they will go out of scope, freeing any stack memory.
void addPort(Communication *com);
...
for (const QSerialPortInfo &serialPortInfo : QSerialPortInfo::availablePorts()) {
// Allocate on the heap
Comunication *com = new Comunication(serialPortInfo.portName());
// Pass pointer to addPort
addPort(com);
}

Does QScopedPointer hide multiple inheritance

I'm having trouble accessing the private part of a PIMPL design. "Of course!", you say! you're supposed to be!
Well, I'm writing some functional tests, so I don't care that I'm accessing private members, ok? :-)
To get to the point, I have the public class set up with a QScopedPointer to the private implementation as follows;
class CV {
...
private:
QScopedPointer<PrivateCV> const _d_ptr;
PrivateChartView * d();
const PrivateChartView *d() const;
};
PrivateCV * CV::d()
{
return _d_ptr.data();
}
const PrivateCV* CV::d() const
{
return _d_ptr.data();
}
and the private bit looks like this:
class PrivateCV : public QObject, public Ui_CVForm
{
Q_OBJECT
friend class MyTestClass;
public:
...
public slots:
void do_something();
}
It seems that MyTestClass can access the do_something() member function of PrivateCV, which it obtains as follows (pseudocode, obvs):
CV *cv = MyApp::get_a_cv();
PrivateCV *pcv = cv->d();
i.e. it will call this fine:
pcv->do_something();
but I can't access anything that is on the Ui_CVForm (the generated UI class from uic).
Ui_CVForm is (in part) as follows:
class Ui_CVForm
{
public:
QGridLayout *gridLayout_2;
QGroupBox *groupBox;
QLineEdit *lineEdit;
};
Is this something to do with the const-ness of the function d(), or the QScopedPointer perhaps?
When I'm inside CV, I can access the ui form elements of the PrivateCV with no problems..
void CV::and_another_thing()
{
d()->lineEdit->setText("wtfa");
}
any pointers (pun intended) most welcome!
OK this turned out to be due to some idiot (me) using the same filename for two different classes in different libraries.
The test library was picking up one header for Ui_CVForm which didn't contain items like the lineEdit above, while PrivateCV was using another... hence no complaints about not seeing the header at compile time.

Qt access D-Pointer of inherited Class

I am trying to understand how the whole d-pointer thing i working. I got most parts but I am currently facing a problem:
Like the guy here Dpointer inheritance i want to inherit a class using d-pointers (infact it is QProcess).
Since the function to access the d-pointer is private i can not access it with simple inheritance. My idea is to again use the Q_DECLARE_PRIVATE macro to get the function and to access it. Can this work? Before I try out I want some hints since I dont know if this can even work.
(I need this to avoid the whole licensing issues.)
MyProcess.h
#ifndef MYPROCESS_H
#define MYPROCESS_H
class QProcessPrivate;
class MyProcess : public QProcess {
public:
MyProcess(QObject *parent = 0);
protected:
Q_DECLARE_PRIVATE(QProcessPrivate);
};
#endif /* WIDGET_H */
MyProcess.cpp
#include "myprocess.h"
MyProcess::MyProcess(QObject *parent = 0)
: QProcess(parent) {
}
MyProcess::setPid(Q_PID pid) {
Q_D(const QProcess);
d->pid = pid;
}
First of all, let's cover the basics. IANAL, but here it goes:
I presume that you have a closed-source application that wishes to use Qt under terms of LGPL.
Under some interpretations of U.S. law, making your code dependent on Qt's private headers makes it a derived work of Qt, so your code must be available under terms of LGPL (or GPL), unless you have a commercial license.
Your obligation under LGPL is to make it possible for people you distribute your app, to relink it with a version of Qt they compiled from the sources you're obliged to offer to them. This may be dynamic linking done by the OS, or static linking done with a linker utility. It doesn't matter whether you modified Qt or not. They ask, you must give them Qt sources with the exact build scripts you used to build the Qt that you use in your app.
When you depend on private headers, it's impossible for someone to make binary compatible changes to the Qt version you offer and relink it with your code, without things breaking. The private Qt classes can be changed without breaking binary compatibility - that's why they are private. Myself I interpret LGPL as follows: My code is not derived work if it will successfully link and work with any version of Qt that's binary-compatible to the version I offer along with my application. Of course that's within limits of Qt bugs and other changes I made, so it may not be viable for someone to patch this Qt to an older version and expect it to run OK.
So, the only thing you can do to keep your code closed-source is to modify the *public interface of QProcess within Qt proper. Anyone can take this modified version of Qt (that you offer!), make further binary compatible changes to it, and relink with your code. So if you think that not modifying Qt and depending on private headers makes your life easier, you are quite off base.
Generally speaking, you can't inherit from QXyzPrivate since you need to include Qt's private headers. So that's not a good practice, and there's really no good reason to do it. The price you pay is an extra heap allocation when you instantiate the class, so I'd say don't worry about it.
You must start your own private PIMPL class hierarchy. Note how each class that intends to be derived from must offer a constructor taking a reference to an instance of the private class.
// myprocess.h
class MyProcessPrivate;
class MyProcess : public QProcess {
Q_DECLARE_PRIVATE(MyProcess) // No semicolon!
public:
explicit MyProcess(int arg, QObject * parent = 0);
~MyProcess();
protected:
MyProcess(MyProcessPrivate&, int arg, QObject * parent); // Must be present to allow derivation
const QScopedPointer<MyProcessPrivate> d_ptr; // Only in the base class, must be protected!
}
// myprocess_p.h
class MyProcessPrivate {
Q_DECLARE_PUBLIC(MyProcess) // No semicolon!
...
public:
explicit MyProcessPrivate(MyProcess*);
protected:
MyProcess * const q_ptr; // Only in the base class, must be protected!
};
// derivedprocess.h
#include "myprocess.h"
class DerivedProcessPrivate;
class DerivedProcess {
Q_DECLARE_PRIVATE(DerivedProcess) // No semicolon!
public:
explicit DerivedProcess(int arg, QObject * parent = 0);
~DerivedProcess();
}
// derivedprocess_p.h
#include "myprocess_p.h"
class DerivedProcessPrivate : public MyProcessPrivate {
Q_DECLARE_PUBLIC(DerivedProcess) // No semicolon!
//...
public:
explicit DerivedProcessPrivate(DerivedProcess*);
};
// myprocess.cpp
MyProcess::MyProcess(int arg, QObject * parent) :
QProcess(parent),
d_ptr(new MyProcessPrivate(this)) {}
MyProcess::MyProcess(MyProcessPrivate & d, int arg) :
d_ptr(&d) {}
MyProcessPrivate::MyProcessPrivate(MyProcess* parent) :
q_ptr(parent) {}
// derivedprocess.cpp
DerivedProcess::DerivedProcess(int arg, QObject * parent) :
MyProcess(* new DerivedProcessPrivate(this), arg, parent) {}
DerivedProcessPrivate::DerivedProcessPrivate(DerivedProcess* parent) :
MyProcessPrivate(parent) {}
It can be accessed by d_ptr.data().
I want to extend the behaviors of QML without recompiling Qt source code, which need access to d_ptr. Here's how I get the QTextDocument in d_ptr of QDeclarativeTextEdit in an inherit class:
QT_FORWARD_DECLARE_CLASS(QDeclarativeTextEditPrivate)
class MyTextEdit : public QDeclarativeTextEdit
{
...
void aMethod()
{
QDeclarativeTextEditPrivate *d = reinterpret_cast<QDeclarativeTextEditPrivate *>(QDeclarativeItem::d_ptr.data());
QTextDocument *d_doc = d->document;
...
}
};
btw, we can also get d_ptr without inheriting classes.
For example, here's how I get QTextDocument in QDeclaractiveTextEditPrivate without inheritance:
#include <QtGui/QGraphicsItem>
QT_FORWARD_DECLARE_CLASS(QGraphicsItemPrivate)
class DQGraphicsItem : public QGraphicsItem
{
DQGraphicsItem() {}
public:
QGraphicsItemPrivate *d() const { return d_ptr.data(); }
};
inline QGraphicsItemPrivate *d_qgraphicsitem(const QGraphicsItem *q)
{ return static_cast<const DQGraphicsItem *>(q)->d(); }
#include <qt/src/declarative/graphicsitems/qdeclarativetextedit_p.h>
#include <qt/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h>
inline QDeclarativeTextEditPrivate *d_qdeclarativetextedit(const QDeclarativeTextEdit *q)
{ return static_cast<QDeclarativeTextEditPrivate *>(d_qgraphicsitem(q)); }
inline QTextDocument *d_qdeclarativetextedit_document(const QDeclarativeTextEdit *q)
{ return d_qdeclarativetextedit(q)->document; }

Change base class of existing derivated class

At the moment I'm writing an application which shows level measurement data into some graphs. Always I have date/time on x-axis and data on th y-axis. I use Qwt for this and modified QwtPlotPicker class to show proper time labels. I did this by derivation and redefining a member function:
class myQwtPlotPicker : public QwtPlotPicker {
Q_OBJECT
public:
explicit myQwtPlotPicker( QWidget* canvas, bool DateScale = false );
explicit myQwtPlotPicker( int xAxis, int yAxis, QWidget* canvas, bool DateScale = false );
explicit myQwtPlotPicker( int xAxis, int yAxis, RubberBand rubberBand, DisplayMode trackerMode, QWidget* canvas, bool DateScale = false );
virtual ~myQwtPlotPicker() {};
protected:
virtual QwtText trackerTextF( const QPointF &position ) const {
... redefinition of the label text ...
}
};
As you can see I also added a new parameter DateScale which turns date labels on or off. This works perfectly, but there is a class QwtPlotZommer which is derivated from QwtPlotPicker:
class QWT_EXPORT QwtPlotZoomer: public QwtPlotPicker { };
Now, the problem is, how do I get the class QwtPlotZommer to derive from myQwtPlotPicker and not from QwtPlotPicker?
Or course I could edit the Qwt sources, but there has to be a proper way of doing this.
I hope there is a proper way to do this. I would be glad, if someone could help me with this.
Try multiple inheritance:
class myQwtPlotZoomer : public QwtPlotZoomer, public QwtPlotPicker { };
There's no way to change class hierarchy at runtime in C++.
I guess that you should reconsider your design - you cannot and should not change the inheritance hierarchy of some library class.
Did you look at some examples to see how the classes you mentioned are intended to be used? Perhaps you should ask a new question to find out how to solve the problem you are actually facing (i.e. how to create a zoomable plot in qwt if I understand you correctly)
You have to overload QwtPlotZoomer reimplementing trackerTextF(). If you also have a use case of a standalone QwtPlotPicker - not being a QwtPlotZoomer - you have to do it twice:
class YourPicker: public QwtPlotPicker ...
class YourZoomer: public QwtPlotZoomer ...
As your implementation is a one-liner I don't see a problem in writing it twice, but if you want to avoid that, you have to put the code to some other class, that is called in both overloaded methods.