Inheritance and pointer arrays - c++

If I have a class that inherit from 2 different classes and I want to put the new class into an array. The array hold pointers to only one of the inherit classes. Will that array overflow or will the pointer-array only “contain” the part of the class that inherit from the class the array is made for?
Example:
I have a class called 'screens' it has 3 arrays of pointers to hold reference to other objects.
class Screens
{
protected:
//Edit these to fit the amount of elements used to save space :-) Then we don't need to use dynamic (8 bit MCU :-()
#define NUMBER_OF_BUTTONS 10
#define NUMBER_OF_GRAPHS 10
#define NUMBER_OF_TXTS 10
UTFT *scr;
UTouch *touch;
ButtonTft *buttons[NUMBER_OF_BUTTONS];
GraphTft *graphs[NUMBER_OF_GRAPHS];
TFT_printer *texts[NUMBER_OF_TXTS];
uint8_t ellementsButtons;
uint8_t ellementsGraphs;
uint8_t ellementsTexts;
uint8_t addButIndex;
uint8_t addGrafIndex;
uint8_t addTxtIndex;
public:
Screens(UTFT *_screen);
void addButton(ButtonTft *but);
void addGraphs(GraphTft *graf);
void addText(TFT_printer *txt);
void printScreen(uint8_t textToPrint = ALL_TXT, graphIDs_e graphToDraw = ALL_GRAPS);
void printButton(uint8_t index,bool presed = false);
void printButton(buttonIDs_e buttonID,bool presed = false);
void printGraph(graphIDs_e graphMode = ALL_GRAPS,bool whatToClear = WHOLE_GRAPH);
void printTxt(uint8_t txtMode = ALL_TXT);
ButtonTft* getButton(buttonIDs_e buttonID);
uint8_t getButtonIndex(buttonIDs_e buttonID);
ButtonTft* getPressedButton(uint8_t x,uint8_t y);
GraphTft* getGraph(graphIDs_e graphID);
GraphTft* getPressedGraph(uint8_t x, uint8_t y);
`};
Then I have another class called “button” that is a button on a screen.
#define PRESSED true
class ButtonTft
{
public:
ButtonTft(UTFT *TFTdisplay, int xTopL,int yTopL, int xButR, int yButR,buttonIDs_e buttonID);
~ButtonTft();
void drawButton(bool pressed = false);
void setPos(int x, int y);//This is never used... remove?
void text(char *txt);
bool isPressed(uint16_t x, uint16_t y);
buttonIDs_e getButtonID();
protected:
buttonIDs_e _buttonID;
uint16_t xTopLeft;
uint16_t yTopLeft;
uint16_t xButRight;
uint16_t yBotRight;
char *butonText;
uint16_t color;
UTFT *scr;
};
Buttons are added to the screen likes this:
/*==============================================================================
| Function Name: addButton
| Description: Adds a button element to the screen.
| Input: A pointer to the button element
| Return: -
*=============================================================================*/
void Screens::addButton(ButtonTft *but)
{
buttons[addButIndex++] = but;//Add the element to the array
if (addButIndex == NUMBER_OF_BUTTONS+1) addButIndex = 0;//Should not do this. Avoid adding more than 10! But Safety first!
if(ellementsButtons++ == NUMBER_OF_BUTTONS+1) ellementsButtons = NUMBER_OF_BUTTONS;//Safety first!
}
And the function is called with a reference to a button object:
module5.addButton(&backButton);
Now I want to make a new class called 'modules', it inherits from both 'screens' and 'button'. My idea was that the module IS a button that HAS a screen with it.
class Modules : public Screens , public ButtonTft
{
public:
Modules(UTFT *_display, int xTopL,int yTopL, int xButR, int yButR, buttonIDs_e buttonID);
bool isConected;
protected:
};
I pass the constructor arguments to the inherited class like this:
Modules::Modules(UTFT *_display, int xTopL,int yTopL, int xButR, int yButR, buttonIDs_e buttonID) : Screens (_display) , ButtonTft (_display, xTopL, yTopL, xButR, yButR, buttonID)
{
isConected = 0;
}
I would like to collect all the modules into a screen object, which means, I would like to put the modules into the button-pointer-array in the 'screen'-object. (Since the modules inherit from the buttons.) I would also like to add other buttons to the 'module'-object as it also inherit from the screen-class.
Modules module5(&display,10,75,100,100,MODULE_5);
module5.addButton(&backButton);
mainScreen.addButton(&module5);
If I add new objects (like new buttons) to my module-object and then add that object to a screen, will the button-reference-array in the screen class overflow?
Thanks for the help.

I see no reason why Modules should inherit from ButtonTft. That would add unnecessary data to Modules. If you need to access protected members of ButtonTft from Modules (which would be bad programming), then make it a friend. The array will not overflow unless you put too many elements into it.

If I understood what you are asking, then no. The arrays only hold pointers, which are of fixed size. It should work fine, although it seems like a convoluted way to do things.

Related

How to declare a class member that may be one of two classes

I am working with a project that is largely not of my creation, but am tasked with adding in some functionality to it. Currently, there is a device class that has a member variable that is responsible for storing information about a storage location, setup like this:
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
StorageInfo.hpp
class StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
I am tasked with implementing a different storage option so that the two can be switched between. The information functions that this new storage option has would be the same as the initial storage option, but the implementation in retrieving that information is vastly different. In order to keep things clean and make it easier to maintain this application for years to come, they really need to be defined in two different files. However, this creates an issue inside of device.cpp, and in every single other file that calls the StorageInfo class. If I create two separate member variables, one for each type of storage, then not only will I need to insert a million different ifelse statements, but I have the potential to run into initialization issues in the constructors. What I would instead like to do is have one member variable that has the potential to hold either storage option class. Something like this:
StorageInfoA.hpp
class StorageInfoA: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
StorageInfoB.hpp
class StorageInfoB: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
device.cpp
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = StorageInfoA();
} else {
storage_info_ = StorageInfoB();
}
// Then, these types of calls would return the correct implementation without further ifelse calls
storage_info_.updateStorageInfo();
However, I know that cpp absolutely hates anything with dynamic typing, so I don't really know how to implement this. Is this kind of thing even possible? If not, does anyone know of a similar way to implement this that does work with cpp's typing rules?
You are on the right track, but you have to learn how to use polymorphism. In your example, you need the following fixes:
In the base class, make all functions virtual, and add a virtual
destructor:
class StorageInfo {
public:
virtual ~StorageInfo(){}
virtual void initializeStorage();
//...
};
Make your inheritance public:
class StorageInfoA: public StorageInfo {
Instead of holding StorageInfo by value, hold it in a smart pointer:
class device {
private:
std::unique_ptr<StorageInfo> storage_info_;
};
device constructor will look like
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = std::make_unique<StorageInfoA>();
} else {
storage_info_ = std::make_unique<StorageInfoB>();
}
Finally, you will use it like an ordinary pointer:
storage_info_->updateStorageInfo();

Access to a method of Object C in an Object B both created by Object A

I think the problem is quite basic and there was the same Question for sure somewhere here but i wasn't able to find.
So here is the Problem. Top has access to MyCircle and calls the SetSize function. But MyCircle has no access to MyRect.
I am able to access MyRect if i am providing a pointer to MyRect within the Constructor of MyCircle, but i think there should be another way. Maybe i just got it wrong at all :( Thanks for your help.
in the
class Top{
public:
Rect myRect;
Circle myCircle;
void Run();
};
class Rect{
public:
int size;
};
class Circle{
public:
int size;
void SetSize(int buffer);
};
void Circle::SetSize(int buffer){
myRect.Size = buffer;
}
void Top:Run(){
myCircle.SetSize(10);
}
Don't pass a rectangle to a circle class, the circle should have no knowledge about the rectangle (or vice versa).
Instead make a function in Top using both the circle and rect and act on that.
I don't know exactly what you want to do, but suppose you want to set the sizes equally. Than make e.g. a SetSize method in Top setting the sizes for both the circle and rectangle:
e.g.
class Top{
public:
Rect myRect;
Circle myCircle;
void Run();
void SetSize(int size)
}
where SetSize is implemented as:
myRect.SetSize(size);
myCircle.size = size;
It's always better to put code handling multiple derived objects in the base class instead of in one of the children. If there will be too much (or unrelated) functionality in the base class, create a different class (like SizeHandler).
btw, it's better not to use public properties but always get/set methods.

How to pass a membervariable as variable itself

Imagine you have a class with 100 or more member variables:
class DataContainer { int a1; int a2; ... double a100; };
and another class which accesses and analysis parts of the variables in the first class:
class Analysis {
protected:
DataContainer *myData;
void myVar1, myVar2;
public:
Analysis() {...}
void myChoice(void a, void b) { myVar1 = a; myVar2 = b }
void Analyse(DataContainer data) {
myData = data;
/* do something with myVar1 and myVar2 */
}
};
but before analysing you have to choose which parameters to use. I would like to know how to write a call for this myChoice-function which is not simply passing the content of a variable, but the choice of the membervariable itself.
In order to ask more generally: I think the position in the memory of a class-member relatively to the class itself is fixed (is it?) Independet if it is a new instance of that class or not. So how can I tell the combiler "Please use the membervariable a3 always". Instead of the content of a3.
This is exactly what pointers-to-data-members are for.
int DataContainer::* myVar1 = &DataContainer::a1;
double DataContainer::* myVar2 = &DataContainer::a100;
I think the position in the memory of a class-member relatively to the class itself is fixed (is it?)
It is indeed. The relative position does not change at run time. This is why pointers-to-data-members work. They can be implemented as a memory offset.
PS. Considering how massive DataContainer is, I would not recommend passing it by value if you can avoid it.
PPS. Consider grouping the member variables into sub-structures.
If the purpose is to have a way to select specific fields in known ways, based on the type of analysis you are doing, then make Analyze virtual pure, and have specific types of analysis pick their fields directly.
From the question, I get the idea that you want to perform the same underlying computation, but use different data points based on the myChoice.
So the whole issue is how do you create the selection metadata? If there are a few specific, well documented ways to do it, then providing each in a subclass will be a very clear, concise and maintainable approach.
class Analysis {
public:
virtual void Analyze(const DataContainer &data) = 0;
virtual ~Analysis();
protected:
void special_computation(int x, int y, double z);
};
class SpecificKindOfAnalysis : public Analysis {
public:
void Analyze(const DataContainer &data){
int x = data.a27;
int y = data.a12;
double z = data.a99;
special_computation(x,y,z);
}
};
This actually looks pretty horrible with variable names like x = data.a27, but I assume we're trying to be general here, and the actual program has meaningful names.

Parent - Child Relation in C++

Consider the below C++ code
class B;
class A{
private:
B* mB;
};
class B{
private:
doSomethingImportant();
};
We have a Object A that contains (has a) Object B. The parent being A and child being B. Now if I want A to make B do doSomethingImportant() , I see that adding A as a friend of B is the only way to do it.
friend class A inside class B. This would enable A's functions to access B's private function.
I find this approach a little weird since creates a loophole in the Data_Hiding concept. Is there a better way to establish a parent-child relationship between the object ? or is this the best way ?
Adding my actual motivation for this question
class elevator{
private:
//The Lift box the elevator controls
liftboxControlUnit & mLiftBoxCtrlUnit;
//constructor
elevator(int Level=1, int NoOfBanks =1 );
//Destructor
~elevator();
//Triggers the search to move to the next floor if required
void moveLiftToNext();
public:
//Adds request to the queue
void addRequest(int FloorNumber){
//Add the request to the queue. The single button outside the elevator door
mLiftBoxCtrlUnit.addRequest(FloorNumber);
}
//For Emergency. Should be accessible to everyone !
void setEmergency();
void unsetEmergency();
};
typedef enum Direction{
UP,
DOWN
}direction;
class liftboxControlUnit{
private:
//The request for various floors
set<int> mRequestQueue;
//The various banks for the whole system
vector<Bank> mBanks;
//The total number of levels. Remains the same for one building
const int mTotalLevel;
//Instruction to move the box to certain level
void processRequest(){
//Do the logic to move the box.
}
//can passed to the elevator
void addRequest(int x){
mRequestQueue.insert(x);
}
//Can be set by elevator class
void setEmergency(){
//Do the required
//Set Emergency on all Banks
}
void unsetEmergency(){
//UnsetEmegency on all banks
}
void emergencyListener(){
//Listen to all the banks if emergency has been set
}
void BankFreeListener(){
//Listen to the banks if any is free
//If so then
processRequest();
}
public:
//Constructor
liftboxControlUnit(int TotalLevels, int NoOfBanks): mTotalLevel(TotalLevels){
for(int i=0 ; i lessthan NoOfBanks; ++ i)
mBanks.push_back(Bank(0,UP));
}
friend class elevator;
};
class Bank{
private:
//The dailpad inside the bank
dailpad & mpad;
//Current Location
int mPresentLevel;
//Current direction of movement
direction mDirection;
//Currently moving
bool mEngaged;
//Manipulate the bank
void move(int NoOfMoves){
setEngaged();
//Move the elevator
unsetEngaged();
}
//getters
int getPresentLevel() const;
int getDirection() const;
//setters
void setPresentLevel(int);
void setDirection(direction);
//Manipulate the engaged flag
bool isEngaged() const;
bool setEngaged();
bool unsetEngaged();
//For emergency
void reset();
//Dailpad Listener
void dailpadListener(){
}
public:
Bank(int StartingLevel, direction Direction): mPresentLevel(StartingLevel),
mDirection(Direction),
mEngaged(false),
mpad()
{
}
//For emergency . Should be available for all.
void SetEmergency();
void UnsetEmergency();
bool isEmergency();
friend class liftboxControlUnit;
};
class dailpad{
private:
//Some DS to represent the state . probably a 2D Array.
void renderDisplay();
public:
//Constructor
dailpad();
void getCommand(int x){
//Depending on the value we can do the following
//Make necessary changes to the display
renderDisplay();
}
friend class Bank;
};
IMO, for this task you should probably nest the "lift box" class inside of the controller class:
class lift_controller {
class lift_box {
open_doors();
close_doors();
move_to_floor();
};
std::vector<lift_box> bank;
};
To the outside world, there need be no evidence that lift_box exists at all. It communicates exclusively with the lift_controller, and all outside communication with a lift_box goes through the lift_controller.
In this case (only lift_controller has access to lift_box at all), it seems clear (at least to me) that any operations the lift_controller may need to invoke on a lift_box should just be made public functions of lift_box. To enforce nobody else having access to lift_box, ensure that the definition of lift_box is in the private: section of lift_controller.
Edit: I should add that quite a bit of the design you've edited into your question above makes little or no sense to me. Just for example, you have things like direction and present level for the bank. Unless I'm completely misunderstanding what you mean by a bank, this seems like a clear error to me -- the bank isn't at a particular level or moving in a particular direction. Rather, each individual elevator in the bank is at some level and (potentially) moving in some direction.
You seem to want class A to only be able to access one private function in B, B::doSomethingImportant() and no other private functions.
This usually means that B::doSomethingImportant() should really be public. Like this, A will not be able to access other private data members of B.
Further, if you do not want other classes to access B::doSomethingImportant(), they should not hold a pointer to B but instead, a hold a pointer to an interface (abstract super class) of B that does not expose B::doSomethingImportant().
Or perhaps other classes only read data from B. In that case they can hold B const * which will not allow them to call B::doSomethingImportant() unless they do a const_cast.

Accessing an object from a different class - Design

I have three classes, TImageProcessingEngine, TImage and TProcessing
TImageProcessingEngine is the one which i am using to expose all my methods to the world.
TImage is the one i plan to use generic image read and image write functions.
TProcessing contains methods that will perform imaging operations.
class TImageProcessingEngine
{
public:
TImage* mpImageProcessingEngine;
};
class TImage
{
public:
int ReadImage();
int WriteImage();
private:
//a two dimensional array holding the pixel values
tImageMatrix* mpImageMatrix;
};
class TProcessing
{
public:
int ConvertToBinary();
int ConvertToGrayScale();
};
My question is how do i access the object mpImageMatrix in class TProcessing? So that my calling application can use the following
TImageProcessingEngine* vEngine = new TImageProcessingEngine;
//Converts an input gray scsale image to binary image
vEngine->ReadImage().ConvertToBinary();
//Write the converted image to disk
vEngine->WriteImage();
delete vEngine;
vEngine = NULL;
//During this whole processing internally,
//the image is read in to `mpImageMatrix`
//and will also be holding the binarised image data,
//till writing the image to disk.
Or Do you recommend any other approach to my class design?
I would certainly recommend a different implementation, but let's check the design first.
I don't really understand the added value of TImageProcessingEngine, it doesn't bring any functionality.
My advice would be quite simple in fact:
Image class, to hold the values
Processing class (interface), to apply operations
Encoder and Decoder classes (interfaces), to read and write to different formats
It does make sense for the Processing class to have access to the images internal only if you can get efficiency from it (which is likely), in this case you can simply makes Processing friend and having it unpack the values for its derived
class Image
{
public:
Image();
void Accept(Processing& p);
void Encode(Encoder& e) const; // Image is not modified by encoding
void Decode(Decoder& d); // This actually resets the image content
private:
friend class Processing;
size_t mHeight;
size_t mWidth;
std::vector<Pixel> mPixels; // 2D array of Pixels
};
class Processing
{
public:
void apply(Image& image)
{
this->applyImpl(image.mHeight, image.mWidth, image.mPixels);
}
private:
virtual void applyImpl(size_t h, size_t w, std::vector<Pixel>& pixels) = 0;
};
Encoder and Decoder follow the same principle.
Note how I never needed an explicit pointer, and the guaranteed correctness that results from it.
First off, based on your provided code there are no ReadImage() & WriteImage() functions in the TImageProcessingEngine class, so the later code where you use such functionality is flawed.
As for the solution, you can make a getter function for the tImageMatrix pointer like this:
tImageMatrix* GetImageMatrix() { return mpImageMatrix; }
Then just pass that pointer (or a pointer to the whole TImage instance) to the TProcessing function you want to call.
Why you want to have a separate TProcessing process, when it specifically has functions just accessing mpImageMatrix;
In OOP, you have to bind the data members and it's operations..
So, IMO, remove your TProcessing class and have both the functions within TImage..
Your TImage will be like,
class TImage
{
public:
int ReadImage();
int WriteImage();
int ConvertToBinary();
int ConvertToGrayScale();
private:
//a two dimensional array holding the pixel values
tImageMatrix* mpImageMatrix;
};
You could create an accessor TImage class:
byte * pixelAt(unsigned x, unsigned y);