Best way to structure classes in C++ - c++

For a long time I have been thinking about following aspect of classes structure. Let's see we have Style class which stores font size, font color and other font-style settings. We have also a Font class.
And now we have two approaches for describing our tasks. The first one is:
class Style {
public:
unsigned short size;
unsigned short color; // just for example
};
class Font{
private:
Style style;
public:
void setSize( unsigned short fontSize ) {
this->style.size = fontSize;
}
void setColor( unsigned short fontColor ) {
this->style.color = fontColor;
}
void setStyle( Style style ) {
this->style = style;
}
};
The second one is:
class Style {
private:
unsigned short size;
unsigned short color; // just for example
public:
void setSize( unsigned short fontSize ) {
this->style.size = fontSize;
}
void setColor( unsigned short fontColor ) {
this->style.color = fontColor;
}
};
class Font{
private:
Style style;
public:
void setStyle( Style style ) {
this->style = style;
}
};
I use Style-object very often in my app:
Style style;
style.size = 10;
style.color = 02034023; // doesn't matter :)
font.setStyle( style );
So if we define setColor, setFont and other voids in Style class we have loaded them all in our memory (by each copy of Style-object). If we define setColor and others in Font class we have just one copy of setColor loaded in a memory. As I use creating of Style object very often I don't want to load setColor and others in a memory just to have an opportunity to use this class something like this: style.setSize( 10 );. Using such technique I load only one copy of setSize and others in a memory.
What do you think about it? Which structures do you use and why?

Option 1
Pros: Partial encapsulation of the Style object
Cons: You have to provide a method in Font for each field in Style. This may work for simple application like this, but imagine you would have Paragraph class that would have its Font and Content fields (or maybe more). Then you would have to either use option 2 or rewrite all the methods from Font again.
Option 2
Pros: You can fully access the Style object from any level of hierarchy
Cons: You have to instantiate a new object every time you want to change something. Problems with object lifetime/ownership coming in. (Do I delete the style here? Is it referenced somewhere else?). Style object has no encapsulation.
My proposal
Use const-correctness with getters:
class Style
{
public:
unsigned short size;
unsigned short color; // just for example
};
class Font
{
private:
Style style;
public:
const Style& GetStyle() const { return style; }
Style& GetStyle() { return style; }
};
This way you clearly state that the ownership of Style object belongs to Font while also enabling it to be read/changed in given places, i.e.
font.GetStyle().size = 14;
Also you can use function signatures to clearly state hat happens with the Font inside.
void AccessFont(const Font& font)
{
unsigned size = font.GetStyle().size; // works
font.GetStyle().size = 16; // doesn't compile
}
And again, if you came to a hierarchy with Paragraph class as mentioned, you would just add the two getters for Font field. You can then pass around the const and non-const version of Paragraph.

I think either is fine.
If you are going to go with Option 1, I suggest you don't provide a setStyle method so the Style is fully encapsulated. That way, clients of Font don't even need to know that Font contains a Style object. Changes in Style only impact Font and you can even change the implementation of Font to not use a Style object in the future without breaking clients.
If Style is unlikely to change and is just a small object that you are going to pass-by-value then I think Option 2 is fine too.

Related

C++ Using classes in other classes failing

I have a Display class that uses SDL to write pixels to the screen. I'd like another class (Triangle) to be able to use this already existent class object, so I've been trying to pass the object by address.
It's sort of working, in the sense that it is actually calling the methods. However, I was getting a segmentation fault in the DrawPixel function. After checking gdb and checking what values are in the function, I figured out that the color_buffer array does not exist (note that when DrawPixel is called directly from the display class in main it works fine).
After a little more testing, I determined that window_width, window_height etc are not set in the Triangle's version of the Display object. But they do exist in the original Display object.
So I'm assuming that I am not properly passing in my object, but I'm uncertain how to fix this issue as I thought passing by address would work just fine. How can I pass an already existing/instantiated class to another class?
I've also tried putting color_buffer into public variables in case private was causing it, but that didn't help.
Example:
main.cpp
int main() {
Display display;
Triangle triangle(&display);
// This doesn't work
triangle.DrawTriangle(300, 500, 0xFFFFFF00);
// This does work
display.DrawPixel(300, 500, 0xFFFFFF00);
return 0;
}
triangle.hpp
class Triangle {
private:
Display* display;
public:
DrawTriangle(int x, int y, uint32_t color);
};
triangle.cpp
Triangle::Triangle(Display* display) {
display=display;
}
Triangle::DrawTriangle(int x, int y, uint32_t color) {
display->DrawPixel(x, y, color);
}
display.hpp
class Display {
private:
// SDL Stuff defined here
uint32_t* color_buffer;
int window_width = 1920;
int window_height = 1080;
public:
Display();
DrawPixel(int x, int y, uint32_t color);
};
display.cpp
Display::Display() {
// SDL Stuff declared
color_buffer = new uint32_t[window_width * window_height];
}
Display::DrawPixel(int x, int y, uint32_t color) {
// This is receiving the correct values, but doesn't allow me to access
// any index of color_buffer.
color_buffer[(y * window_width) + x] = color;
}
Triangle::Triangle(Display* display) {
display=display;
}
the display is not the member of your class.Use this->display = display instead
You have to use "this" in Triangle constructor. That should solve the problem.
Triangle(Display* display) {
this->display=display;
}
A couple of things to add to the answers above:
use a different naming convention for member variables - this way it is very easy to avoid typos. _display, m_display, Display_ (Clang style =) )
class members are private by default so if you are following convention where attributes are defined on top, there's no need to add private:
Some prefer references (e.g. Display&), mostly to save typing ->, since if `Display goes out of scope it will have the same hilarious effect as passing a pointer.
static analyzers look down on pointer arithmetic(due to possible out-of-bounds writes).
You can use std::array from header:
static constexpr int WIDTH = 1920;
static constexpr int HEIGHT = 1080;
std::array<uint32_t, WIDTH* HEIGHT> m_color_buffer{};
and then either use m_color_buffer[index] = color (no bounds checking, random memory gets written if you write out of bounds in release and normally an exception in debug), or use m_color_buffer.at(index) - slower but this way you get an exception in release mode, but the compiler may complain about the stack size, as the definition is essentially the same as uint32_t buffer[WIDTH*HEIGHT]. std::vector is a better alternative - it hides buffer allocation, manages memory (no need to delete) at expense of the 2 extra pointers for begin and the end of the vector.
The code example lacked a destructor. Every new should have an accompanying delete hence either add it or just switch to a standard library container to avoid the headache =)
Last but not least - both classes override constructors. Display also manages resources. What happens when you copy Display instances? Move them? It is a bit of a headache and leads to a bit of a boilerplate, but it is best to implement Rule of 5 members and avoid accidental surprises =)
PS. C++ is a beautiful language =)

What is the best way to initialize a more complex class construct with many unchangeable members in c++

I'm currently designing classes that should represent a chaotic storage system.
Lets say we have slots in rows and columns with certain properties.
So the slots have different restrictions in min/max height, width, length, weight and some more that come from a parameter file.
Also the Slots have a max total weight that must be checked before a new parcel gets added to that slot. And also the max weight that a row of slots can hold is lower than the sum of the max weights of the single slots. So for example each individual slot might be able to hold 50kg but the row of 10 slots must not exceed 200kg, so it is not allowed to fill every slot by 100%. The same is true for the Columns where the maximum weight is lower than the sum of the individual weights of the single rows. The row_id and column_id are atrificial numbers for adressing the slot in the physical system with barcodes or whatever that get read for positioning.
As all this parameters do not change over the lifetime of the program, my intention was to design the classes in a way that this properties are readable by getter functions but there should not be any setter functions (maybe not even private ones) in the object o the values cannot be changed by accident.
There is one class/function that reads the config-file and generates the data structure for the rows and columns with the slots. This function should be able to read the config and create objects for every column holding a row of slots and pass all the values from the config down to the slot.
Later when the program is running I also need some way to search for the best matching slot to add the next parcel or for searching parcels and unload them in a certain sequence.
So the (simplfied) basic structure of the classes would be like this:
Class Parcel {
int width;
int height;
int length;
int weight;
}
Class Slot {
vector<Parcel> parcel;
int min_width;
int max_width;
int min_height;
int max_height;
int min_length;
int max_length;
int max_total_weight;
int act_total_weight;
int total_length;
int free_length;
}
Class Row {
vector<Slot> slot;
int row_id;
int max_total_weight;
int act_total_weight;
}
Class Column {
vector<Row> row;
int column_id;
int max_total_weight;
int act_total_weight;
}
Class Storage {
vector<Column> column;
}
So here are my thoughts about how to initialize the data structure:
First possibility would be to pass all the properties in the constructor(s) of the classes, but then the constructors has some huge parameter lists specially for the Slot class that has a lot of properties.
Second thing that came to my mind (and currently my fafourite way to go) is to use config-data-structures that hold all the parameters. This parameter-objects get filled by the config-function and passed to the constructor when initializing the class. Then it also may be useful to use the parameter class as such and not having all the parameters defined in the storage class once more.
Third way is to use private setter and public getter and make the config class friends with the data structure classes to be able to access the setter functions (but i would prefer to have no setters at all in the final storage structure classes.
Fourth way that i was thinking off, was to derive child classes from the structure classes that hold the setter functions (and also some other logic needed for creating the data structure) so the child has no own variables but only additional functions. So the child class is used to fill the properties but the base class gets added to the data structure vector.
I also want to use Factory pattern to initialize the data structure because the objects have often similar or only slightly different properties. So with the second aproach after creating one row of slots I would maybe want to change the max weight of the slots in that row. Therefore I would need to change the setting in the factory and the factory then fills the parameter data structure differently and passes it to the Slot class. Or is it better to pass the data structure to the factory directly and the factory assigns it but then i think this is not what the factory pattern is meant to be.
I don't know if this is a good aproach or which of the above is best practice.
Or am I missing something and there is a way more convenient solution or this?
Thank you (and sorry if the question is maybe not the way it should be)
When constructing your classes as you describe it you can have a look at the creational design patterns.
Your second proposed solution is almost a builder design pattern. This will help you to construct the Slot e.g. piecewise.
As an example:
#include <iostream>
class Slot {
public:
int GetMinWidth() const { return min_width_; };
int GetMaxWidth() const { return max_width_; };
// Builder class
class SlotBuilder {
public:
SlotBuilder& SetMinWidth(int min_width) {
min_width_ = min_width;
return *this;
}
SlotBuilder& SetMaxWidth(int max_width) {
max_width_ = max_width;
return *this;
}
Slot Build() {
return Slot(min_width_, max_width_);
}
private:
int min_width_{/* you can add default value here*/};
int max_width_{/* you can add default value here*/};
};
// This is optional, but creates a neat interface
static SlotBuilder Create() {
static SlotBuilder slot_builder;
return slot_builder;
}
private:
// Make constructor private to restrict access and force the use of the builder
Slot(int min_width, int max_width) : min_width_(min_width), max_width_(max_width) {}
const int min_width_;
const int max_width_;
// .
// .
// Continue with your const attributes
};
int main() {
// Create the slot with the builder
Slot slot = Slot::Create()
.SetMinWidth(10)
.SetMaxWidth(20)
.Build();
std::cout << slot.GetMinWidth() << ", " << slot.GetMaxWidth();
return 0;
}
You can see the example working here
For having different types that are almost the same a Prototype pattern could work if you want to "clone" a class or in your case a Factory pattern could do the job.
There is never an ideal solution or that one pattern that solves it all, so I can't give you a definitive answer, but here are some collected thoughts:
Default values
Primitive types like int don't have a default value, so make sure you give them one explicitly:
struct Parcel {
int width{};
int height = 0;
int length = {};
int weight{};
}
All those different versions above are equivalent, but you really should use one of them. Otherwise you will probably run into UB down the line.
Const correctness
One thing that I love about C++ and that I dearly miss in languages like C# is const correctness. If you want an object to be immutable, declare it as const. To prevent changes to your objects, either instantiate the object as a const:
const Parcel x;
x.width = 10; // compiler error
or make the members of your classes const:
struct Parcel {
const int width{};
const int height{};
const int length{};
const int weight{};
};
Parcel x;
x.width = 10; // compiler error
Aggregate initialization
If you keep your types simple enough you can initialize the class members with curly braces directly:
const Parcel x { 1, 2, 3, 4 };
In C++ 20, you can also name the members, so this code is equivalent to the line above:
const Parcel x { .width = 1, .height = 2, .length = 3, .weight = 4 };
Note that this can bite you later though if you have to deal with ABI stability and versioning. In that case you are better off using getter and setter functions, because that allows you to still change the data layout of your members.
I have to think about design patterns a bit more. I'll update this post if something useful comes out of it.

How can I access to derived members from a pure virtual base class function?

I want to have a Collider interface class in which will have a overloaded -> operator to have access directy to the BoxCollider derived class. I want to have access to the members of box collider through the interface and chnage the type of collider at run-time.
So I thought of using templates:
template<typename T>
class ColliderV2 {
public:
virtual T* operator ->() = 0;
};
class BoxColliderV2 : public ColliderV2<BoxColliderV2> {
public:
float width;
float height;
BoxColliderV2* operator ->() {
return this;
}
};
int main()
{
ColliderV2<BoxColliderV2>* col = new BoxColliderV2;
(*col)->width = 1;
}
This works. But templates , as far as I know, will generate a brand new Collider class in compile-time filling T with Box Collider, correct? Thats why it worked. But later it prevents me from changing the collider type. I also thought of just making a virtual Collider class with Collider* operator->() ; overload in the derived class BoxCollider* operator->() ;
But if I tried :
Collider<BoxCollider>* col = new BoxCollider;
(*col)->width = 1; // won't work
doesn't work since Collider is not BoxCollider. And I don't want to dynamic_cast every possible collider type I could have. So, what can be done here?
As you've already found out, this doesn't work. Templates and runtime behavior are kind of contradicting mechanics. You can't create a common base class and let it act like a generic pointer to give you access to its derived types' members.
An interface specifies a contract against which you can code. You don't code against a specific implementation but the interface, so the interface has to provide all the members that you'd like to access. In your case this would result in width and height beeing part of ColliderV2 instead of BoxColliderV2. However this defeates the logic you are trying to mimic.
There are a few approaches that you can take:
Either make your collider type a variant, like
using ColliderType = std::variant<BoxColliderV2, MyOtherCollider, ...>;
and check for the actual type when you want to access the member
ColliderType myCollider = /* generate */;
if (auto boxCollider = std::get_if<BoxColliderV2>(&myCollider); boxCollider)
boxCollider->width = 0;
Or, keep the base class that you have, remove the operator-> and the template and do a dynamic cast on it:
ColliderV2* col = new BoxColliderV2;
if (auto boxCollider = dynamic_cast<BoxColliderV2*>(col); boxCollider)
boxCollider->width = 0;
You can also hide details like width or height behind more generic functions that are part of the interface. For example:
class ColliderV2 {
public:
virtual void setBounds(float width, float height) = 0;
};
class BoxColliderV2 : public ColliderV2 {
public:
void setBounds(float width, float height) override {
this->width = width;
this->height = height;
}
private:
float width;
float height;
};
int main()
{
ColliderV2* col = new BoxColliderV2;
col->setBounds(1, 1);
}
What you are trying to do is discouraged by C++. What you are trying to do is to change the type of something based on the return value of a function. The type system is designed to stop you from writing code like this.
One important restriction of a function is that can only return one type-of-thing. You can return one of a list of things if you wrap those possibilities in a class, and return that. In C++17, a ready-made class for this is std::variant. The restriction on this is that the list of things must be fixed (or a closed-set). If you want an arbitrary set of return values (open-set), you must use a different approach. You must restate your problem in terms a function that is done on the return value.
class BoxColliderV2 : public MyBaseCollider {
public:
void SetWidth(float new_width) override;
};
You may find this video useful. The bit of interest starts at around 40 minutes (but watch the whole video if you can). If you are interested in advice, I would suggest starting with std::variant, and if it works, move to virtual functions. Problems like collision detection get really complicated really quickly, and you will almost certainly require double dispatch at some stage. Start simple, because it's only going to get more complicated.
These excerpts from the ISO-Guidelines may help
1. When you change the semantic meaning of an operator, you make it
harder for other programmers to understand you code. guideline.
2. Dynamic casting is verbose and ugly, but deliberately so, because dynamic casting is dangerous, and should stand out. guideline
I think you are approaching the problem from the wrong direction. The purpose of an interface is that you don't have to know about the exact type or the implementation.
For example: You are using Axis-Aligned Bounding Boxes for collision detection. So, even if your CircleCollider uses a radius, you are still able to calculate its width and height from it. Now, you don't have to worry about if you are dealing with a BoxCollider or a CircleCollider, you have everything to make a Bounding Box.
class Collider
{
public:
virtual float x() const = 0;
virtual float y() const = 0;
virtual float width() const = 0;
virtual float height() const = 0;
};
class BoxCollider : public Collider
{
// Implementation...
};
class CircleCollider : public Collider
{
// Implementation...
};
Of course, you are maybe using something else, and not AABBs. I just wanted to demonstrate how you can use interfaces effectively.

Override VCL class/component protected method - How to code and use?

I am rewriting old existing code and I'm giving the icons an overhaul. I used to have bitmaps assigned to TMenuItems but I'm changing that in favor of ImageIndex and a TImageList with colordepth 32bit, containing icons with an alpha channel. The ImageList is created and populated with icons at design time. The ImageIndex are assigned during program startup and changed if/when appropriate.
I noticed that when a MenuItem is disabled (enabled = false), the resulting image doesn't look great (at all) and I read that this is due to VCL. Mentioned link also links to Delphi code that can convert an icon to its greyscale values.
I'm not fluent in Delphi nor changing VCL components, subclassing them, inheriting from them etc. I normally simply use what is available without changing it. so I'm starting with some basic questions:
Here's a very simple attempt to inherit from TImage and override DoDraw(), to make it never disable the icon in the first place (decipering the Delphi code to greyscale can be done in a second step)
class MyTImageList : public TImageList
{
public:
__fastcall MyTImageList(Classes::TComponent* AOwner)
: TImageList(AOwner) {} ;
virtual __fastcall DoDraw(int Index, TCanvas *Canvas, int X, int Y, unsigned int Style, bool Enabled = true)
{
return TImageList::DoDraw(Index, Canvas, X, Y, Style) ;
}
};
FYI: I use C++ Builder 2009
It does not compile, error: [BCC32 Error] Main.h(1018): E2113 Virtual function '_fastcall TMainForm::MyTImageList::DoDraw(int,TCanvas *,int,int,unsigned int,bool)' conflicts with base class 'TCustomImageList'
Since I'm very insecure about inheriting from VCL component classes I'm not sure if I'm dealing with a typo or something very constructively wrong ? Kindly enlighten me.
Assuming this compiles I'm actually not sure how to proceed further either.
Because the ImageList is created at design time, and used throughout the code. For this change to work I have to work with 'MyTimageList'.
So, do I create MyTimageList during Form construction and Assign() the content of the design-time-ImageList, or is there a more efficient way to avoid copying over everything ?
Actually, thinking about the latter question more, I could simply use the internal ImageList of the design time Imagelist instance.
Here is a C++ translation of the Delphi code:
class MyTImageList : public TImageList
{
protected:
virtual void __fastcall DoDraw(int Index, Graphics::TCanvas *Canvas, int X, int Y, unsigned Style, bool Enabled = true);
public:
__fastcall MyTImageList(Classes::TComponent* AOwner, TImageList *DesignImageList);
};
__fastcall MyTImageList::MyTImageList(Classes::TComponent* AOwner, TImageList *DesignImageList)
: TImageList(AOwner)
{
ColorDepth = DesignImageList->ColorDepth;
Handle = DesignImageList->Handle; // Use the internally kept List of the design time ImageList
ShareImages = true;
}
unsigned __fastcall GetRGBColor(TColor Value)
{
unsigned Result = ColorToRGB(Value);
switch (Result)
{
case clNone: Result = CLR_NONE; break;
case clDefault: Result = CLR_DEFAULT; break;
}
return Result;
}
void __fastcall MyTImageList::DoDraw(int Index, TCanvas *Canvas, int X, int Y, unsigned Style, bool Enabled)
{
if ((Enabled) || (ColorDepth != cd32Bit))
{
TImageList::DoDraw(Index, Canvas, X, Y, Style, Enabled);
}
else if (HandleAllocated())
{
IMAGELISTDRAWPARAMS Options = {0};
Options.cbSize = sizeof(Options);
Options.himl = (HIMAGELIST) Handle;
Options.i = Index;
Options.hdcDst = Canvas->Handle;
Options.x = X;
Options.y = Y;
Options.cx = 0;
Options.cy = 0;
Options.xBitmap = 0;
Options.yBitmap = 0;
Options.rgbBk = GetRGBColor(BkColor);
Options.rgbFg = GetRGBColor(BlendColor);
Options.fStyle = Style;
Options.fState = ILS_SATURATE; // Grayscale for 32bit images
ImageList_DrawIndirect(&Options);
}
}
OK, the answer is simple, and it needed some trial and error to get there, because the documentation I had access to was not clear about that. (E.g. also wrong about the TCanvas pointer).
The function/method returns void. THAT's what was missing in the originally posted code and what caused the error. I got following code to work nicely.
class MyTImageList : public TImageList
{
public:
__fastcall MyTImageList(Classes::TComponent* AOwner, TImageList *DesignImageList)
: TImageList(AOwner)
{
Handle = DesignImageList->Handle ; // Use the internally kept List of the design time ImageList
ShareImages = true;
}
protected:
virtual __fastcall void DoDraw(int Index, TCanvas *Canvas, int X, int Y, unsigned int Style, bool Enabled = true)
{
return TImageList::DoDraw(Index, Canvas, X, Y, Style, true /*Enabled*/) ; // Always draw enabled
}
};
This issue is closed.

C++: Global variable vs local variables. What to use?

Sometimes I wanna use globals but instead of it I use local variables. Let we have some Font class:
class Font {
public:
class Alignment {
public:
unsigned short currentAlignment;
unsigned short FONT_ALIGN_LEFT = 0;
unsigned short FONT_ALIGN_CENTER = 1;
unsigned short FONT_ALIGN_RIGHT = 2;
// etc....
};
Alignment alignment;
void setFontAlignment( unsigned short fontAlignment ) {
this->alignment.currentAlignment = fontAlignment;
}
};
To use this class we need to do something like that:
Font font;
font.setFontAlignment( font.alignment.FONT_ALIGN_CENTER );
// if we need to check currentAlignment we need to do:
if ( font.alignment.currentAlignment == font.alignment.FONT_ALIGN_CENTER ) {...} // looks a little bit awful :)
Or we have another approach to do this:
= Font.h =
#define FONT_ALIGN_LEFT 0
#define FONT_ALIGN_CENTER 1
#define FONT_ALIGN_RIGHT 2
// etc....
class Font {
public:
unsigned short currentAlignment;
void setFontAlignment( unsigned short fontAlignment ) {
this->currentAlignment = fontAlignment;
}
}
To use this:
#include "Font.h"
...
Font font;
font.setFontAlignment( FONT_ALIGN_CENTER );
if ( font.currentAlignment == FONT_ALIGN_CENTER ) {...} // looks a little bit better :)
Which one is better for memory optimizing and why? Which one do you prefer to use? Or maybe you know some better solutions?
Although there are always exceptions, I usually go by (among others :-) the following guidelines:
Avoid globals as much as possible. Confine to smallest applicable
scope (within reason).
Avoid second guessing the compiler, except for grossly obvious
situations.
Actually, a combination of them. But let's clarify something. You don't speak about any global variable in your question. A global variable is a variable defined in the global scope.
The primary reason of using object oriented programming is not its efficiency (as it is slower than purely procedural code), but its ability to model the world. So, when creating an oop design, you shouldn't care too much about the resourced (time, memory), but how good it models the world.
The second version is bad, because it introduces a lot of constants in the global scope, and you want to avoid that. Also, it does a very bad job at encapsulating the data (the user of your Font class shouldn't care about the values of the alignment).
The first version is better, but there are some problems. First, you need to think about the objects you should have? Do you actually need an Alignment object? You may need it, but in this particular example, I don't see why. So, you could make it model the world as it is, without introducing some artificial elements:
class Font {
public:
unsigned short currentAlignment;
void alignLeft() {
this->currentAlignment = 0;
}
void alignCenter() {
this->currentAlignment = 1;
}
void alignRight() {
this->currentAlignment = 2;
}
};
Now it is very easy to use. I don't have to keep in my global scope unnecessary constants. Now, the problem is what happens when the user reads the value of the currentAlignment? Of course, you don't want to use the constants, but you don't need to. It really depends on the world you're modelling. As this is a Font class, it should be the only one who really cares about the value of the alignment. If somebody else needs the value, you could have some methods like isCenter() that return true when the font is center-aligned. But also, I would consider making the currentAlignment private.