How do I tell a class to create unique sub-classes - c++

I have defined a class called Instrument which I initialise by calling a function in the class to it the name of the Instrument to put up on the display.
I now create two Instruments:
Instrument Organ
Instrument Piano
I also have another class called Screen which handles changing values such as volume and putting those values on the display. For example it has a function called IncValue() which does what it says.
I want to create subclasses that can be repeated for all Instruments such as :
Screen Volume
This would declare int16_t volume and IncValue() would increment the volume, DecValue() reduce it.
But how do I create those Screens from the Instrument Class such that I can do things like
Organ.Volume.IncValue()
(or -> maybe, I've got totally lost on this level of complexity)
and
Piano.Volume.IncValue()
and they only work on the relevant Instrument.
Eventually there will be 100s of Instruments declared so I really don't want to declare unique Classes such as Screen PianoVolume and Screen OrganVolume.
Hope this isn't too long-winded a question.

I think you are getting mixed up between classes and objects. Just have class Instrument own an object of class Screen. The rest then follows naturally.
So you might have (expanding on your ideas a little bit):
class Screen
{
public:
void IncValue ();
private:
int volume;
};
class Instrument
{
public:
Screen screen;
...
};
class Piano : public Instrument
{
...
};
And then you can do (for example):
Piano MyPiano;
MyPiano.screen.IncValue ();
...
for any Instrument or subclass of Instrument.

Related

C++ Derived classes cannot modify a base class' attributes but an external class can

I am doing a Poker Engine so that different PokerPlayer agents can play against each other in tournament simulations. Once my project is done, I would like people to submit their own agents in a PR. In order to do so, they would only have to derive the PokerPlayer class with their MyPokerPlayer class and override the play() method. But I want to make sure that their agents don't cheat. I don't want them to be able to change the money that they have, nor do I want them to be able to change the cards that they have been given at the beginning of the game.
The problem is that the Game class needs to be able to take a PokerPlayer's money when they bet (or give them the pot when they win) and needs to be able to set the PokerPlayer's card at the beginning of the Game. So PokerPlayer's derived classes cannot directly update their own money and cards but the external class Game can.
PokerPlayer.h (This is the class that sould be derived by agents)
class PokerPlayer
{
private:
bool alive = true;
QList<Card> cards;
int money;
public:
PokerPlayer();
int getMoney() const;
bool isAlive() const;
virtual Action* play() = 0;
};
Game.cpp (where I assign the Players their cards, take their bets, etc...)
...
void Game::assignCardsToEveryPlayer() {
foreach (PokerPlayer* player, this->getPlayers()) {
QSet<Card> cards = PokerGameManager::generateUniqueCards(2);
player->setCards(cards.toList());
}
}
...
What I do not want:
MYPokerPlayer.cpp (An Agent)
Action* MYPokerPlayer::play() override {
this->setMoney(1000000);
this->setCards(ACE, ACE);
// you get the idea...
}
How could I achieve this?
Thank you for your time,
Let's review the concepts behind your classes. PokerPlayer is one of the players. This player is in charge of tracking if it is alive, which cards it has, and how much money it has. Does that sound like an accurate simulation of a game that does not allow cheating?
No? Why not? For one thing, the dealer/house decides who gets which cards. Players can view the cards but not change them. So your class should be similar. (The money is an interesting aspect to analyze, as a real player might bring an ATM card... ;) ) Players buy their chips, sit down, and make moves. Everything else is controlled (or at least overseen) by the house. The player brings just the starting money and the brains (i.e. how to play()).
Let's see if we can model a poker game more accurately. There are a bunch of people sitting around a table. On the table there are a number of cards, some of which can be viewed by certain players. So... perhaps what you call a "player" should be more accurately deemed a "chair" after you take away the play method. The table owns the chairs, gives each chair cards, and handles moving poker chips to/from the chair (from/to the pot).
Each player could be reduced to a view of the table (used for making bets, folding, etc.), a const view of their chair (used to see their cards and status), plus the virtual play method. The player joins the game by buying chips from the table, then the table assigns them a chair. The player can only influence the game via the methods provided by the table.
Admittedly, cheating is still possible (e.g. cast away the const from the chair). The C++ language is not about security within source code. The guardrails that exist are there to prevent accidental infringements; they will not stop maliciousness from someone else working on the same program. Still, you could introduce a level of indirection to make things a little more secure. The chair given to players to look at could be a copy of the chair maintained by the table. A malicious programmer manipulating their copy of the chair would not change what the table tracks.
You can store money and other values which shouldn't be cheated as private members of your base class and limit their changes to only PokerPlayer's private functions, which should be called by the Game or whatever is supposed to be capable of changing ones:
class Game;
class PokerPlayer {
friend class Game;
private:
int money;
public:
int getMoney() const;
};

Qt C++ creating an Object according to choice in combobox

Since I am not very experienced in the design of object orientated code, I have the following question:
I have a combobox cb_GRAN with 21 entries representing 21 geometries. According to the choice made in cb_GRAN I want start different calculations of the surface of my geometry (actually there is more: more complicated calculatins, on/of-switching of LineEdits etc. but to keep it simple let`s just talk about the calculation of the surface. )
To solve this problem I created a class Geometry and 21 Classes (Geo_1, Geo_2,...Geo_21) which inherit from Geometry. I also have a virtual method
virtual void calculateSurface();
To define which class Geo_x is to create and to calculate the surface I came up with the following idea:
Geometry *GEO;
QVector < Geometry*> qvec_GEO
qvec_GEO << new Geo_1()<< new Geo_2()<< new Geo_3()<<...... << new Geo_21() ;
GEO = qvec_GEO[ui->cb_GRAN->currentIndex()];
GEO->calculateSurface();
Would that be a doable approach to solve my problem or would I run into problems when doing so?
Is it a good idea to create as much as
21 objects when I would need just one?
Question 1:
Your solution will probably work well (only based on information you provided).
Question 2:
You're totally right, creating instance of all your 21 class if you are going to use only 1 or 2 of them is probably an overkill.
You have to find a solution to instantiate only the needed class. Qt provide a Meta-object system you could use for this. Basically, you will have to use the QMetaType class.
First, you have to register the "Geo_N" classes in the meta-object system. You have many solutions to do that, but maybe the best in your case is to use the declarative macro after your class definition:
class Geo_1 {
Q_OBJECT
void Geo_1();
};
Q_DECLARE_METATYPE(Geo_1);
Please note that Q_OBJECT macro is mandatory if you want to register a class in the meta-object registry.
Then, you will be able to instantiate any registered type dynamically:
// The index of selected class (between 1 and 21)
int geoIndex = ui->cb_GRAN->currentIndex();
// Re-build the corresponding class name
QString typeName = "Geo_" + QString::number(geoIndex);
// Retrieve the type ID corresponding to the type name
int typeId = QMetaType::type(typeName.toStdString().c_str());
// Instantiate the corresponding class
Geometry* geo = (Geometry*) QMetaType::construct(typeId);
My Approach would be to define a factory class for your geometries
class GeoFactory{
enum GeometryType { GEO_1, GEO_2, ... );
std::uique_ptr<Geometry> create( GeometryType type );
}
And then add the GeometryType to your combobox items in the data role. On the current changed event you just retrieve the GeometryType from the current index and request the corresponding object from the factory.
Personally i always try to keep out Qt from the actual business logic, i just use for UI.

Class design for device driver and graphics

Banging my head on the wall trying to organize what I feel should be (and probably is) a simple set of relationships between some classes.
Basically trying to tie together 3 classes together in a way that makes sense.
Simplified scenario with 3 classes:
1 - LCD device driver
2 - Simple graphics library
3 - Counter display class
What I've got so far in pseudocode:
class Driver : public Graphics
{
public:
void loadImage(int * image){
// load image into device memory
}
};
class Graphics
{
public:
int image[10];
void displayImage(int * image){
// create/ manipulate image here and...
loadImage(image); //send to device
}
virtual void loadImage(int * image){}
};
class Counter
{
public:
int counterImage[10];
void makeCounter(int * counterImage){
//make a clock counter graphic and…
displayImage(counterImage);
}
};
Obviously, I've not figured out how to get the displayImage(counterImage) function integrated into the Counter class. I could virtual a version of displayImage() in the Counter class, but I'm assuming that that would entail that Graphics would always have to inherit Counter, which I'm not keen on. Is there a better way to allow Counter to access the Graphics class functions (ultimately passing through to the LCD driver) while still remaining separate from it?
Why do you want to use inheritance at all?
Based on the description on your classes, I don't see any specialization / kind of relation between them, which means you you should use composition in this case:
the graphics Driver needs the ability to display some Image (a type not present in your example)
the Graphics image loading library needs the ability to load an Image
the Counter display should use both a Driver and a Graphics, both given to it in its constructor, displaying the counter with them.
This concept is called composition over inheritance, you can get a lot more good articles on it with google. (Basically: OOP and using classes doesn't mean you have to use inheritance for everything)

Passing application objects into lower level classes

I wasn't really sure how to search for this question.
I'm doing an embedded system design with the following scenario.
I have a main application class that needs to create a bunch of hardware interfaces such as a keypad, display, communication ports, etc... a whole slew of stuff
Now I have all these objets in the main application that I can use which is great
The application class contains a few sub classes that it can go into and stay for a while. One example is a menu class that it enters and runs inside that class until the menu is closed
I need the menu class to also interact with a lot of a hardware objects that were created at the application level
What is the best way to go about this without using global variables? Is there a good solution to this problem?
I could pass each object into the menu class, but I don't want to create a constructor with 20 arguments. My current solution is to put all the objects into a structure and pass that structure into the sub-class constructor. That way they also have access.
The part that bugs me about this approach is that I have to define the structure outside of the application which I don't really like. Something just keeps telling me it's not the best solution.
Open to any suggestions.
Presumably, there is ONE keypad - thus only one "Keypad Interface Object", right? Similarly with Display [ok, there may be two displays, but still].
So my suggestion would be to have a registration and a "container" that holds the registered interfaces something like this:
class KeyPad
{
public:
int getKeyPressed();
};
class Display
{
public:
OutputText(std::string msg);
};
... bunch of other stuff ...
class HardwareRegistry
{
priviate:
Keypad *keypad;
Display *display;
static HardwareRegistry *myself;
public:
Keypad* GetKeypad() { return keypad; }
Display* GetDisplay() { return display; }
void RegisterKeypad(Keypad *akeypad) { keypad = akeypad; }
void RegisterDisplay(Display *adisplay) { display = adisplay; }
static HardwareRegistry* GetHwRegistry()
{
if (!myself) myself = new HardwareRegistry;
ASSERT(myself); // If we don't have a pointer now, panic!
return myself;
}
};
Then you just have a Singleton Pattern to provide your HardwareRegistry, and register the devices as you create them during hardware initialization.
Of course, if you support different kinds of Keypads, Displays, etc, then you would implement those with a "interface baseclass", and the registry returns the KeypadBase type, for example.

C++/Qt - multiple inheritance with QGraphicsItem doesn't work as expected

I recently met a strange problem of my little program and it would be great if you help me to get the reason of this behavior.
My task is quiet simple - I want to use Qt Graphics Framework to show some objects and I want Box2D to calculate bodies position. So my class hierarchy looks like the following:
I have 1 base abstract class B2DObject. It contains some Box2D staff + some common parameters for its successors (names, some flags, etc.). It also has couple of pure virtual functions that will be reimplemented in successor classes.
Then I implement some classes that represent basic shapes: circles, rectangles, polygons, etc. I am doing it in the following way:
class ExtendedPolygon : public B2DObject, public QGraphicsPolygonItem { ... };
class ExtendedCircle : public B2DObject, public QGraphicsEllipseItem { ... };
etc.
(for those who are not familiar with Qt, QGraphics***Item is inherited from QGraphicsItem).
Also I inherited QGraphicsScene and reimplemented its mousePressEvent. In this function I request an object placed at some point on the screen using QGraphicsScene::itemAt function (which returns QGraphicsItem*), convert it to B2DObject* and try to get some internal field from this object:
void TestScene::mousePressEvent (QGraphicsSceneMouseEvent *event)
{
QGraphicsItem* item = itemAt (event->scenePos ());
if (item)
{
B2DObject* obj = reinterpret_cast < B2DObject* > (item);
QString objName = obj->Name(); // just for example,
// getting other internal fields has
// the same effect (described below)
// use retrieved field somehow (e.g. print in the screen)
}
// give the event to the ancestor
}
Unfortunately, dynamic_cast will not work here because these classes are completely unrelated.
Then I create necessary objects and add it to my scene:
ExtendedPolygon* polygon = new ExtendedPolygon (parameters);
polygon->setName (QString ("Object 1"));
...
TestScene scene;
scene.addItem (polygon);
(for those who are not familiar with Qt, here is the prototype of the last function:
void QGraphicsScene::addItem(QGraphicsItem *item);
I guess it just stores all items in internal index storage and calls QGraphicsItem::paint (...) when item needs to be repainted. I suppose QGraphicsScene doesn't make any significant changes to this item).
So my problems start when I run the program and click on an item on the screen. TestScene::mousePressEvent is called (see a piece of code above).
Mouse click position is retrieved, item is found. Casting works fine: in the debugger window (I'm using Qt Creator) I see that obj points to ExtendedPolygon (address is the same as when I add the item to the scene and in the debugger window I can see all the fields). But when I get some field, I receive garbage in any case (and it does not matter, what I'm trying to get - a QString or a pointer to some other structure).
So first of all, I would like to get any advice about my multiple inheritance. In 95% of cases I try to avoid it, but here it is very effective in the programming point of view. So I would appreciate it if you provide me with your point of view about the architecture of the classes hierarchy - does it even suppose to work as I expect it?
If on this level everything is quite fine, then it would be great if someone gets any idea why doesn't it work.
I have some ideas about workaround, but I really would like to solve this problem (just in order not to repeat the same error anymore).
Looks like I've found the root cause of my problem. It was just lack of knowledge regarding how multiple inheritance really works on data layer.
Let's assume that we have 2 basic classes, A and B. Each of them provides some internal data fields and some interfaces.
Then we create a derived class AABB, inheriting both A and B:
class AABB : public A, public B {...}
AABB could add some additional data fields and reimplement some of the interfaces, but it is not necessary.
Let's create and object of class AABB:
AABB* obj = new AABB ();
For example, obj points at address 0x8416e0. At this address starts data from ancestor class A. Data from ancestor class B starts with some offset (it should bw equal to sizeof (A)), for example, at 0x841700.
If we have some function f (B* b), and if we pass a pointer at AABB object to that function (like this: f (obj), obj is created above), actually not obj start address is passed, but rather a pointer at a start of B data section of AABB object.
Thus this misunderstanding of multiple inheritance inner works has led me to the problem I've got.
I guess Qobjects and multiple inheritance has been already treated. As an example: QObject Multiple Inheritance