I have two classes
class Car
{
// class Car related methods
public:
setDriversName(QString);
private:
String driversName_; // This information comes from class DriversName
//Must get the drivers name info, when a particular event in this object occurs;
}
class DriversName
{
//class DriversName related methods
String getDriversName();
private:
String driversName_;
}
So, now i want to communicate between the two classes, more specifically i want class Car
to get the driver's name from the DriversName
class when a particular event occours in Car Object.
So far i have these two ways,
C++ Message passing:
class Car
{
// class Car related methods
public:
setDriversNameObject(DriversName& );
setDriversName()
{
driversName_ = DriversName.getDriversName();
}
private:
DriversName driversName_; // So after setting the Driverclass object, i can directly
//access the driver's name, whenever the event occurs
String driversName_;
}
class DriversName
{
//class DriversName related methods
String getDriversName();
private:
DriversName driversName_;
}
OR
Qt
In mainWindow class:
connect(carObject,eventHasOccured(),this,updateDriversName());
void MainWindow::updateDriversName()
{
carObject->setDriversName(driversNameObject.getDriversName);
}
Class Car
{
Q_OBJECT
signals:
emit eventHasOccured();
public:
setDriversNameObject(DriversName& );
private:
DriversName driversName_;
}
Class DriversName
{
Q_OBJECT
String getDriversName();
private:
DriversName driversName_;
}
Both the Solutions will definitely work. Here are my questions:
1) Is there any flaw in the above methods, with respect to OO principles.
2) Which is the most standard way this situation can be dealt with ?
3) is there any other better method to handle the given situation.
Thanks.
A few more details on top of nyarlathotep's answer:
1) If you definitely need the update to take place when a particular event occurs, then the first solution is not enough because it does not handle events; one should explicitly call
Car
'ssetDriversName()
. You do need a signal/slot, or callback mechanism in general, like the second solution. It that case, I think you would rather need something likewhere neither the application/main window nor the
carObject
need to know anything about adriversNameObject
. Besides that, I think there are a number of little errors in your second solution (e.g., there is nosetDriversName
method inCar
.2) and 3) I would personally avoid QT's signal/slot mechanism if I am not already working in a QT project. This mechanism bypasses the C++ language entirely and needs source file preprocessing by its own tools. One consequence is that everything (like method names) is processed as a string, before the compiler has any chance for checking. Another is that you need a specific way to build your project that is way more complicated than necessary and would make the use of other libraries more difficult.
As for more "pure C++" solutions, I bet e.g. Boost.Signals would do the job, but again it would probably bring too many complexities that you don't need.
I have developed a pure-C++ abstract interface that mimics exactly the behavior of QT signals/slots based on delegates, but this involves low-level stuff internally like casting to
void*
. An alternative would be of course to usestd::function
in the internals. It is still not completely generic in handling all function-call language features, e.g. methods in derived classes, overloading, virtual methods, default arguments, and so on (but neither is Boost.Signals). I intend to re-implement it in C++11 using variadic templates before completing it.Again, I am (still) not aware of a perfect or de facto standard solution.
The first approach couples the
Car
method closely to theDriversName
class.The second couples your application to Qt. If you use it throughout your whole application anyway, that's not much of a problem, but it should be considered. Also, it moves business logic code into the mainwindow class, which might not be such a good idea.
There is no "one definitive way" of doing this. Just better and worse ones.
For the "pure C++" approach, you could introduce an abstract interface for listening to driver name changes (or maybe even more generically for listening to generic name changes). What I'm referring to here is basically implementing the Observer pattern. A simplified implementation could e.g. look like this:
For the Qt approach, it might be good to introduce an additional "Controller" class encapsulating such relations, instead of doing it directly in the main window.