Setters and getters in C++ - c++

Coming from Java, I am used to doing this:
void setColor(String color) {
this.color = color;
}
However, I recently switched to C++, and I see a lot of this instead:
void setColor(string c) {
color = c;
}
Why not this? Is this not recommended?
void setColor(string color) {
this->color = color;
}

It's the exact same thing. In Java if you had named your parameter c instead of color, you would not have any shadowing and you could easily write
void setColor(String c) {
color = c;
}
The this in Java (or C++ for that matter) is only needed to specify exactly which color you are referring to: the member variable or the local variable.

There is no need to use this, because there is no conflict between local and member variable and no fields are hidden. Generally you don't want this conflict to happen at all by not having same variable as an constructor parameter and also as local variable (despite so many books teach you exactly this).
I find this is much more smooth(and also more readable even if you don't have background from particular language):
private String localColor;
void setColor(String color) {
localColor = color;
}

Related

How to get a property name and offset in a class at compile time or runtime?

I have a class named SoftInfo.
class SoftInfo
{
public:
std::string m_strSoftName;
std::string m_strSoftVersion;
std::string m_strInstallLocation;
}
I want to export it to lua in a c++ program via sol3. I write something like this and I can use it in lua world. However, there are something unconvenient. I need to write the name and offset of any property of class SoftInfo. When I change the property name in SoftInfo, I also need to change the name in function Export. Besides, if the number of properties of SoftInfo is too large, it will be very hard to write the Export function manually.
void Export(lua_state _state)
{
_state.new_usertype<SoftInfo>("SoftInfo",
"m_strSoftName",&SoftInfo::m_strSoftName,
"m_strSoftVersion",&SoftInfo::m_strSoftVersion,
"m_strInstallLocation",&SoftInfo::m_strInstallLocation);
}
or
void Export(lua_state _state)
{
sol::usertype<SoftInfo> usertype_table = _state.new_usertype<SoftInfo>("SoftInfo");
usertype_table["m_strSoftName"] = &SoftInfo::m_strSoftName;
usertype_table["m_strSoftVersion"] = &SoftInfo::m_strSoftVersion;
usertype_table["m_strInstallLocation"] = &SoftInfo::m_strInstallLocation;
}
I wonder is there a way to avoid these complicated work like macro that I can wirte something like this? If other solution can reduce the complicated manual working, it is not limited to the solution pattern I supplied below.
class SoftInfo
{
public:
//Macro or something defined here
std::string m_strSoftName;
std::string m_strSoftVersion;
std::string m_strInstallLocation;
}
void Export(lua_state _state)
{
sol::usertype<ship> usertype_table = _state.new_usertype<SoftInfo>("SoftInfo");
for(auto [properties,offset]:Func(SoftInfo))
usertype_table[properties] = offset;
}
What you're asking for is called static reflection. Unfortunately, C++ doesn't have that. However, with boost describe, you may get quite close
#include<boost/describe.hpp>
BOOST_DESCRIBE_STRUCT(SoftInfo, (),
(m_strSoftName,
m_strSoftVersion,
m_strInstallLocation))
void Export(lua_state _state)
{
sol::usertype<SoftInfo> usertype_table = _state.new_usertype<SoftInfo>("SoftInfo");
using namespace boost::describe;
using M = describe_members<SoftInfo, mod_any_access>;
boost::mp11::mp_for_each<M>([&](auto d){
using D = decltype(d);
usertype_table[D::name] = D::pointer;
});
}
BOOST_DESCRIBE_STRUCT has to be maintained manually by filling in all the members but Export will be automatically implemented.

function inside objects oop

I don't understand what is the point of having a function inside an object if you can even modify data outside the object for example (I'm using struct for this example):
int lamborghini_horsepower1 = 350;
struct car {
string model;
string color;
int horsepower;
void check(int horsepower) {
if (horsepower > 349) {
cout << "this car has many horsepowers";
}
}
};
car ford;
ford.check(lamborghini_horsepower1);
in this case it would run anyways.
it would make sense if the function could only operate inside data of the object because as it say they are the data of the object and why can the function access to others variables? for example what if you pass another variable in this case lamborghini_horsepower is not part of the the object ford. and still can be cecked by the ford function even if they are different veichle.
are for class different?
In structs, functions don't have too much of an impact because data can be modified from the outside. However, they still can act as a convenience feature, especially when properly written. Your function takes horsepower as an argument, which is unnecessary because horsepower is already a field in the struct. If you change your function to:
void check() {
if (horsepower > 349) {
cout << "this car has many horsepowers" << endl;
}
}
you can call it with ford.check() and it'll automatically retrieve the horsepower from the ford variable. In classes, fields can be declared as private, which means that they can't be accessed from the outside and must be modified purely with functions defined inside the class.
are for class different?
Classes are not accessible from the outside by default, so if you did
class car{
string model;
string color;
int horsepower;
void check(int horsepower) {
if(horsepower>349)
{
cout << "this car has many horsepowers";
}
}
};
Then nothing in that struct would be accessible from outside the class. But there is a way to modify the what variables and functions can be accessed from the outside with access modifiers.
The purpose of making functions and variables inaccessible outside the object is to protect them from being unintentionally called or altered
The short answer is that your example wouldn't be very efficient for objects. I would just keep the function outside the struct in that example.
The purpose of classes and structs is to put variables and functions into one package. The example you have doesn't require an object. The basis behind object design is to mimic real world objects by giving them abilities(functions) and properties (variables).
The check() function here isn't an ability we normally find in cars. Instead, a car has certain properties like color, speed, and direction. A car also has abilities like accelerate, reverse, turn left and turn right. With this we can create a car object with these properties (variables) and abilities (functions)
struct Car
{
int speed;
std::string color;
std::string direction;
Car() // As soon as the object is created, this function will be called and set speed to 0.
{
speed = 0;
}
void speedUp()
{
speed += 5;
}
void slowDown()
{
speed -= 5;
}
void stop()
{
speed = 0;
}
void reverse()
{
stop() // This will stop the car first
speed -= 2; // Move the car backwords
}
void turnLeft()
{
direction = "left";
}
void turnRight()
{
direction = "right";
}
};
So now you can create different objects of the same class\struct with different speeds, direction, and color.

C++ passing "default" struct to function

I'm trying to figure out how I can "pass default struct values" to a function without initializing the struct, this is what I have now:
struct Color3i
{
Color3i(): r(255), g(255), b(255) { }
int r, g, b;
};
void CCore::Color(Color3i color)
{
double red, green, blue;
red = color.r / 255.0f;
green = color.g / 255.0f;
blue = color.b / 255.0f;
glColor3f(red,green,blue);
}
Color3i defaultColor;
Core.Color(defaultColor);
What I'm trying to do would look like this but this clearly doesn't work:
Core.Color(Color3i defaultColor);
How would I pass the struct to the function without initializing it with Color3i defaultColor; is this possible?
Sorry if this has been asked before but I tried searching the interwebs but I couldn't find anything (maybe I'm using the wrong keywords to search)
You should just be able to do this:
Core.Color(Color3i());
That is, call the default constructor to initialize a new instance, and pass it.
There are a few ways to pass an information that you want the color to be default. The simplest one is given in the comments already:
Core.Color(Color3i())
If you want the code to be shorter, you can set the default value in the function parameter you invoke:
void CCore::Color(Color3i color = Color3i()) { ... }
....
Core.Color(); //no argument = default
If you want to be more descriptive instead, you can create a static function acting as a constructor in the Color:
struct Color3i {
Color3i(): r(255), g(255), b(255) { }
int r, g, b;
static Colo3i defaultColor() { return Color3i(); }
};
...
Core.Color(Color3i::defaultColor());
Finally, if you want to control the context where the default color can be used, you can create a new dummy enum type and overload the function(s) to accept the default version explicitly:
enum DefaultColorEnum {
DefaultColor
};
void CCore::Color(Color3i color) {
... //normal code
}
void CCore::Color(DefaultColorEnum) { //ignore the parameter value, the type is what matters
Color(Color3i()); //invoke the generic version with default value
}
...
Core.Color(DefaultColor);
It all depends on what you actually wants to achieve...

Get/Set function to change text and color

Im trying to make a class called Label. Labels are plain text controls. One should be able to change the text and color of a label through get/set functions. I think this is a way to change the text of the label through get/set function. But Im not sure about the color. Any advice would be appriciated.
<pre>
class Label
{
private:
std::string text;
int color;
public:
Label();
void SetText(string Ntext);
void SetColor(int value);
int GetColor();
string GetText();
~Label();
};
<code>
<pre>
Label::Label()
{
}
string Label::GetText()
{
return text;
}
void Label::SetText(string Ntext)
{
text = Ntext;
}
int Label::GetColor()
{
return color;
}
void Label::SetColor(int value)
{
color = value;
}
Label::~Label()
{
}
<code>
You can make color an array containing red blue and green.
int color[3];
void SetColor(int red, int green, int blue){
this->color[0] = red;
this->color[1] = green;
this->color[2] = blue;
}
Besides the question of how to represent the color (which actually varies depending on how the class will be used, for example, it can be something as simple as red, black, white, etc strings), another thing to consider is that having getters and setters is not good in terms of OOP.
The idea of OOP is to hide the data inside the objects and instruct these objects to do something useful (send them messages).
With getters and setters you open the internal implementation (it is actually the same as if you define the text and color as public properties. It doesn't sound good, right? But this is actually what it is, you can read and modify them as if they are public.
So the better implementation could be to have both text and color to be constructor parameters. This way label has enough information to be displayed, so you don't need to have setters / getters, something like this:
class Label
{
private:
std::string text;
int color;
public:
Label(string text, string color);
~Label();
// display the label on the `canvas`
void display(Canvas* canvas);
};
More information on the topic of getters / setters:
Why getter and setter methods are evil
More on getters and setters
Getters/Setters. Evil. Period.

Best way to structure classes in 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.