Using Qt5 new connect syntax with inheritance - c++

I am trying to use the new connect syntax in some legacy code but came upon an architectural problem. So let's pretend I have a BaseReader class that looks like this :
class BaseReader : public QObject
{
Q_OBJECT
public:
BaseReader();
public slots:
virtual void read(const fstream& myStream);
}
Then let's say I have some children classes like this
class Reader1 : public BaseReader
{
Q_OBJECT
public:
BaseReader();
public slots:
virtual void read(const fstream& myStream);
}
Some of the read work is done in the base class, some in the child class. I have about 4 classes that are switched around at runtime. I have a connectReaders function that looks like this :
void connectReaders(BaseReader* currentReader)
{
connect(this, SIGNAL(mustRead(const fstream&)), currentReader, SLOT(read(const fstream&)));
}
Now it is my understanding that if I use the new syntax I will connect to the base member function no the overloaded versions. Is that correct ? Is there any way to connect these signals using the new syntax without modifying the architecture ? My example is very simplified and modifying that code would require a couple of months (including tests). It works the old way but I would like to take advantage of the new syntax. Any ideas ?
I have looked at these threads but they do not seem to offer a solution to this problem :
This is the other way around:
Using Qt signals and slots with multiple inheritance
I have read this but I am not sure I understand how the overload
section applies: https://wiki.qt.io/New_Signal_Slot_Syntax
I have qt5.4.1, Visual Studio 2013.

There's no problem when using the new 'connect' syntax with virtual slots and base class object pointers. You're specifying the object instance (e. g. currentReader), and the specific method to be called will be resolved using this object's virtual methods table.

Disclaimer: I am not familiar with Qt. The question here however, seems to be a C++ question.
When using a pointer-to-member to a virtual function in a base class, on a pointer/reference to a derived class, an override in the derived class will be called (if it exists).
class Base
{
public:
virtual void f()
{
std::cout << "Base\n";
}
};
class Derived : public Base
{
public:
virtual void f()
{
std::cout << "Derived\n";
}
};
int main()
{
void (Base::* pmf)() = &Base::f;
Derived d;
(d.*pmf)();
}
Will print "Derived", not "Base";
If a Qt signal calls your member function pointer with a derived object, the function override will therefore get called.

Related

Inheritance: Child uses parent virtual function instead of its own

I'm having this issue with inheritance I just cannot wrap my head around. I have three classes, with a parental relationship between them. All of them has the function calcForces().
class Object {
public:
virtual void calcForces();
};
class Boat : public Object {
public:
virtual void calcForces();
};
class Sailboat : public Boat {
public:
void calcForces(Wind wind);
};
Now my problem is that I I have a object created as a Sailboat (and saved it in an Object-pointer), but when I call calcForces() I end up inside Boat::calcForces(), not Sailboat::calcForces(). What am I doing wrong?
Here is my call to the function:
(*this->object_ptr_arr[i]).calcForces(); //'object_ptr_arr' is of type 'Object**'
The declarations of the overrides must match. Your declaration for Sailboat::calcForces takes a different parameter (a Wind instance) and therefore is not an override.
As commented by #stefaanv and #skypjack you can avoid this issue by embracing the use of the override function specifier, which would've caught the error at compile time.
If you want an calcForces() method in your sailboat you should add it there.
At the moment you only have a calcForces(Wind wind) method in your sailboat (and the calcForces() that is inherited from Boat)
So when you are calling calcForces without a parameter it will end up in the inherited method. To fix this either add it in Sailboat like described above or call it with an variable of type Wind
Suggestion - boats and sailboats exist in an environment. The boat knows how it is affected by the environment.
class Environment
{
public:
Wind wind;
};
class Object {
public:
virtual void calcForces(Environment const&);
};
class Boat : public Object {
public:
virtual void calcForces(Environment const& env); // can ignore the wind
};
class Sailboat : public Boat {
public:
void calcForces(Environment const& env) override; // will use env.wind in calculation
};
Now you are able to modify the environment and ask all objects in the environment to calculate their forces. Whether they're boats, sailboats or dolphins.

Why can not I call virtual function from base class slot Qt

Can someone explain to me why is the overridden method is not being called in base class slot, instead I have a base version of method:
class ThreadsDispatcher : public QObject
{
Q_OBJECT
public:
explicit ThreadsDispatcher(QObject *parent = 0);
virtual ~ThreadsDispatcher();
virtual void OnThreadFinished(IThreadable *pWorker);
public slots:
void slotThreadFinished(IThreadable *pWorker);
};
void ThreadsDispatcher::slotThreadFinished(IThreadable *pWorker)
{
OnThreadFinished(pWorker);
}
void ThreadsDispatcher::OnThreadFinished(IThreadable *pWorker)
{
qDebug << "Base method, class" << this->metaObject()->className();
}
A subclass:
class CommandsQueueDispatcher : public ThreadsDispatcher
{
Q_OBJECT
public:
explicit CommandsQueueDispatcher(CommandFactory* baseFactory, QObject *parent = 0);
~CommandsQueueDispatcher();
void OnThreadFinished(IThreadable *pWorker);
};
void CommandsQueueDispatcher::OnThreadFinished(IThreadable *pWorker)
{
qDebug << "Subclass method, class" << this->metaObject()->className();
}
After call OnThreadFinished in slot I get:
Base method, class ThreadsDispatcher
If I call method OnThreadFinished from another method, I get normal:
Subclass method, class CommandsQueueDispatcher
I have tried to connect in base class and subclass, but there no changes:
connect(pThreadWorker, SIGNAL(sigFinished(IThreadable*)), this, SLOT(slotThreadFinished(IThreadable*)));
But if I connect from another class, i.e. neither subclass, nor base class:
connect(pThreadWorker, SIGNAL(sigFinished(IThreadable*)), pWorker, SLOT(slotThreadFinished(IThreadable*)));
where I need to replace this with the variable ptr, I get a normal result.
Function where I connect:
bool ThreadsDispatcher::AddThread(IThreadable* pThreadWorker)
{
connect(pThreadWorker, SIGNAL(sigFinished(IThreadable*)), this, SLOT(slotThreadFinished(IThreadable*)));
}
I don't instantiate ThreadsDispatcher directly. I create the CommandsQueueDispatcher's object non-static.
A troubleshooting suggestion (too long for a comment):
Try changing the slot to be like this:
void ThreadsDispatcher::OnThreadFinished(IThreadable *pWorker)
{
qDebug << "Base method, class" << this->metaObject()->className();
}
And same for derived class. See what is output.
If output is "correct" in the sense that called virtual method is consistent with the class name, then I suspect you somehow do have a base class object, instead of derived class object.
If there's output mismatch, base class virtual method does the print but reports derived class name, then I'd look for any funny compiler flags, and try to create a SSCCE with a fresh project, then perhaps ask again here and/or file a bug report to Qt.
A link for starting to read about this in Qt docs.
A seconds step in troubleshooting: change the base class to be abstract, by making this method abstoract in base class:
virtual void OnThreadFinished(IThreadable *pWorker) = 0;
...and then remove the method definiton. Now compiler should tell you where you try to create an instance of base class.
One more suggestion: the Qt build basics, listed for example in this answer. In particular, make sure QObject subclasses are defined in .h files, which are listed in .pro file HEADERS list.

Restricting method call to another method

There probably is a fairly simple and straight-forward answer for this, but for some reason I can't see it.
I need to restrict calling methods from a class only to some methods implemented by derived classes of some interface.
Say I have
class A{
public:
static void foo();
};
class myInterface{
public:
virtual void onlyCallFooFromHere() = 0;
}
class myImplementation : public myInterface{
public:
virtual void onlyCallFooFromHere()
{
A::foo(); //this should work
}
void otherFoo()
{
A::foo(); //i want to get a compilation error here
}
}
So I should be able to call A::foo only from the method onlyCallFooFromHere()
Is there a way to achieve this? I'm open to any suggestions, including changing the class design.
EDIT:
So... I feel there's a need to further explain the issue. I have a utility class which interacts with a database (mainly updates records) - class A.
In my interface (which represents a basic database objects) I have the virtual function updateRecord() from which I call methods from the db utility class. I want to enforce updating the database only in the updateRecord() function of all extending classes and nowhere else. I don't believe this to be a bad design choice, even if not possible. However, if indeed not possible, I would appreciate a different solution.
Change the class design - what you want is impossible.
I am unsure of what you are trying to achieve with so little details and I am unable to comment further.
[Disclaimer: this solution will stop Murphy, not Macchiavelli.]
How about:
class DatabaseQueryInterface {
public:
~virtual DatabseQueryInterface() = 0;
virtual Query compileQuery() const = 0; // or whatever
virtual ResultSet runQuery(const Query&) const = 0; // etc
};
class DatabaseUpdateInterface : public DatabaseQueryInterface {
public:
virtual Update compileUpdate() const = 0; // whatever
};
class DatabaseObject {
public:
virtual ~DatabaseObject() = 0;
protected:
virtual void queryRecord(const DatabaseQueryInterface& interface) = 0;
virtual void updateRecord(const DatabaseUpdateInterface& interface) = 0;
};
class SomeConcreteDatabaseObject : public DatabaseObject {
protected:
virtual void updateRecord(const DatabaseUpdateInterface& interface) {
// gets to use interface->compileUpdate()
}
virtual void queryRecord(const DatabaseQueryInterface& interface) {
// only gets query methods, no updates
}
};
So the basic idea is that your DatabaseObject base class squirrels away a private Query object and a private Update object and when it comes time to call the protected members of the subclass it hands off the Update interface to the updateRecord() method, and the Query interface to the queryRecord() method.
That way the natural thing for the subclasses is to use the object they are passed to talk to the database. Of course they can always resort to dirty tricks to store away a passed-in Update object and try to use it later from a query method, but frankly if they go to such lengths, they're on their own.
You could split your project into different TUs:
// A.h
class A
{
public:
static void foo();
};
// My.h
class myInterface
{
public:
virtual void onlyCallFooFromHere() = 0;
}
class myImplementation : public myInterface
{
public:
virtual void onlyCallFooFromHere();
void otherFoo();
};
// My-with-A.cpp
#include "My.h"
#include "A.h"
void myImplementation::onlyCallFooFromHere() { /* use A */ }
// My-without-A.cpp
#include "My.h"
void myImplementation::otherFoo() { /* no A here */ }
You probably know this, but with inheritance, you can have public, protected, and private member access.
If a member is private in the base class, the derived cannot access it, while if that same member is protected, then the derived class can access it (while it still isn't public, so you're maintaining encapsulation).
There's no way to stop specific functions from being able to see whats available in their scope though (which is what you're asking), but you can design your base class so that the derived classes can only access specific elements of it.
This could be useful because class B could inherit from class A as protected (thus getting its protected members) while class C could inherit from the same class A as public (thus not getting access to its protected members). This will let you get some form of call availability difference at least -- between classes though, not between functions in the same class.
This could work.
class myInterface;
class A {
private:
friend class myInterface;
static void foo();
};
class myInterface {
public:
virtual void onlyCallFooFromHere() {callFoo();}
protected:
void callFoo() {A::foo();}
};
Though at this point I think I'd just make A::foo a static of myInterface. The concerns aren't really separate anymore.
class myInterface {
protected:
static void foo();
};
Is there a reason foo is in A?

How can I resolve interface method and base class method name conflict in C++ Builder?

I have the following abstract base class, SettingsInterface, that I use as an interface:
class SettingsInterface
{
public:
virtual void Refresh() = 0;
virtual void Update() = 0;
virtual void OnConnect() = 0;
virtual void OnDisconnect() = 0;
};
I'm trying to implement this interface in my class below, which inherits from TFrame. TFrame inherits from another class that also has a virtual method called Update.
class DebugSettingsFrame : public TFrame, public SettingsInterface
{
//a bunch of IDE-managed components - left out for brevity
public:
virtual void Refresh();
virtual void Update();
virtual void OnConnect();
virtual void OnDisconnect();
};
When I compile this, I get the error virtual function DebugSettingsFrame::Update() conflicts with base class 'TWinControl'.
I'm stomped on this. How can I resolve this without changing my interface's method definition, Update, to something else?
Edit - Follow-up:
So C++ doesn't have a construct similar to C# where you can explicitly implement interface methods that have the same definition?
Thanks!
Try something like (from the code I can't say exactly):
DebugSettingsFrame::TFrame::Update();
:: is the scope resolution operator. You should be able to specify precisely which version of the function you are calling.
However, note that this is a symptom of a design that may be getting too complex.

Registering derived classes in C++

EDIT: minor fixes (virtual Print; return mpInstance) following remarks in the answers.
I am trying to create a system in which I can derive a Child class from any Base class, and its implementation should replace the implementation of the base class.
All the objects that create and use the base class objects shouldn't change the way they create or call an object, i.e. should continue calling BaseClass.Create() even when they actually create a Child class.
The Base classes know that they can be overridden, but they do not know the concrete classes that override them.
And I want the registration of all the the Child classes to be done just in one place.
Here is my implementation:
class CAbstractFactory
{
public:
virtual ~CAbstractFactory()=0;
};
template<typename Class>
class CRegisteredClassFactory: public CAbstractFactory
{
public:
~CRegisteredClassFactory(){};
Class* CreateAndGet()
{
pClass = new Class;
return pClass;
}
private:
Class* pClass;
};
// holds info about all the classes that were registered to be overridden
class CRegisteredClasses
{
public:
bool find(const string & sClassName);
CAbstractFactory* GetFactory(const string & sClassName)
{
return mRegisteredClasses[sClassName];
}
void RegisterClass(const string & sClassName, CAbstractFactory* pConcreteFactory);
private:
map<string, CAbstractFactory* > mRegisteredClasses;
};
// Here I hold the data about all the registered classes. I hold statically one object of this class.
// in this example I register a class CChildClass, which will override the implementation of CBaseClass,
// and a class CFooChildClass which will override CFooBaseClass
class RegistrationData
{
public:
void RegisterAll()
{
mRegisteredClasses.RegisterClass("CBaseClass", & mChildClassFactory);
mRegisteredClasses.RegisterClass("CFooBaseClass", & mFooChildClassFactory);
};
CRegisteredClasses* GetRegisteredClasses(){return &mRegisteredClasses;};
private:
CRegisteredClasses mRegisteredClasses;
CRegisteredClassFactory<CChildClass> mChildClassFactory;
CRegisteredClassFactory<CFooChildClass> mFooChildClassFactory;
};
static RegistrationData StaticRegistrationData;
// and here are the base class and the child class
// in the implementation of CBaseClass::Create I check, whether it should be overridden by another class.
class CBaseClass
{
public:
static CBaseClass* Create()
{
CRegisteredClasses* pRegisteredClasses = StaticRegistrationData.GetRegisteredClasses();
if (pRegisteredClasses->find("CBaseClass"))
{
CRegisteredClassFactory<CBaseClass>* pFac =
dynamic_cast<CRegisteredClassFactory<CBaseClass>* >(pRegisteredClasses->GetFactory("CBaseClass"));
mpInstance = pFac->CreateAndGet();
}
else
{
mpInstance = new CBaseClass;
}
return mpInstance;
}
virtual void Print(){cout << "Base" << endl;};
private:
static CBaseClass* mpInstance;
};
class CChildClass : public CBaseClass
{
public:
void Print(){cout << "Child" << endl;};
private:
};
Using this implementation, when I am doing this from some other class:
StaticRegistrationData.RegisterAll();
CBaseClass* b = CBaseClass::Create();
b.Print();
I expect to get "Child" in the output.
What do you think of this design? Did I complicate things too much and it can be done easier? And is it OK that I create a template that inherits from an abstract class?
I had to use dynamic_pointer (didn't compile otherwise) - is it a hint that something is wrong?
Thank you.
This sort of pattern is fairly common. I'm not a C++ expert but in Java you see this everywhere. The dynamic cast appears to be necessary because the compiler can't tell what kind of factory you've stored in the map. To my knowledge there isn't much you can do about that with the current design. It would help to know how these objects are meant to be used. Let me give you an example of how a similar task is accomplished in Java's database library (JDBC):
The system has a DriverManager which knows about JDBC drivers. The drivers have to be registered somehow (the details aren't important); once registered whenever you ask for a database connection you get a Connection object. Normally this object will be an OracleConnection or an MSSQLConnection or something similar, but the client code only sees "Connection". To get a Statement object you say connection.prepareStatement, which returns an object of type PreparedStatement; except that it's really an OraclePreparedStatement or MSSQLPreparedStatement. This is transparent to the client because the factory for Statements is in the Connection, and the factory for Connections is in the DriverManager.
If your classes are similarly related you may want to have a function that returns a specific type of class, much like DriverManager's getConnection method returns a Connection. No casting required.
The other approach you may want to consider is using a factory that has a factory-method for each specific class you need. Then you only need one factory-factory to get an instance of the Factory. Sample (sorry if this isn't proper C++):
class CClassFactory
{
public:
virtual CBaseClass* CreateBase() { return new CBaseClass(); }
virtual CFooBaseClass* CreateFoo() { return new CFooBaseClass();}
}
class CAImplClassFactory : public CClassFactory
{
public:
virtual CBaseClass* CreateBase() { return new CAImplBaseClass(); }
virtual CFooBaseClass* CreateFoo() { return new CAImplFooBaseClass();}
}
class CBImplClassFactory : public CClassFactory // only overrides one method
{
public:
virtual CBaseClass* CreateBase() { return new CBImplBaseClass(); }
}
As for the other comments criticizing the use of inheritance: in my opinion there is no difference between an interface and public inheritance; so go ahead and use classes instead of interfaces wherever it makes sense. Pure Interfaces may be more flexible in the long run but maybe not. Without more details about your class hierarchy it's impossible to say.
Usually, base class/ derived class pattern is used when you have an interface in base class, and that interface is implemented in derived class (IS-A relationship). In your case, the base class does not seem to have any connection with derived class - it may as well be void*.
If there is no connection between base class and derived class, why do you use inheritance? What is the benefit of having a factory if factory's output cannot be used in a general way? You have
class CAbstractFactory
{
public:
virtual ~CAbstractFactory()=0;
};
This is perfectly wrong. A factory has to manufacture something that can be used immediately:
class CAbstractFactory
{
public:
virtual ~CAbstractFactory(){};
public:
CBaseClass* CreateAndGet()
{
pClass = new Class;
return pClass;
}
private:
CBaseClass* pClass;
protected:
CBaseClass *create() = 0;
};
In general, you're mixing inheritance, virtual functions and templates the way they should not be mixed.
Without having read all of the code or gone into the details, it seems like you should've done the following:
make b of type CChildClass,
make CBaseClass::Print a virtual function.
Maybe I'm wrong but I didn't find any return statement in your CBaseClass::Create() method!
Personally, I think this design overuses inheritance.
"I am trying to create a system in which I can derive a Child class from any Base class, and its implementation should replace the implementation of the base class." - I don't know that IS-A relationships should be that flexible.
I wonder if you'd be better off using interfaces (pure virtual classes in C++) and mixin behavior. If I were writing it in Java I'd do this:
public interface Foo
{
void doSomething();
}
public class MixinDemo implements Foo
{
private Foo mixin;
public MixinDemo(Foo f)
{
this.mixin = f;
}
public void doSomething() { this.mixin.doSomething(); }
}
Now I can change the behavior as needed by changing the Foo implementation that I pass to the MixinDemo.