Proper design of member setters/getters in a C++ class - c++

The usual way of designing setters and getters for a class member is the following
class QNumber
{
public:
void setNumber(unsigned int xNumber){ this->mValue = xNumber; };
unsigned int getNumber(void) const { return this->mValue; };
private:
unsigned int mValue;
}
If the member is another class (e.g. QRational as opposed to unsigned int), then the getter would be better returning a reference, in terms of performance.
So the modified design would be
class QNumber
{
public:
const QRational & value(void) const { return mValue;} // getter
QRational & value(void) { return mValue;} // 'setter'
private:
QRational mValue;
}
My question is - isn't there something potentially wrong with the latter approach? I have not seen it much in other people's code and to me, it seems more elegant than set/get method.
Many thanks,
Daniel

The point of getters and setters is to separate the interface from the implementation. If you return a reference, it has to point somewhere in the implementation. Now if you change the implementation, you'll have to start returning by value instead.
Personally I prefer public nonstatic members when the need for anything else is unlikely. Reference-semantic getters and setters provide the worst of both worlds. (I am working on a proposal to improve them, though.)

In addition to Potatoswatter's answer, please note one more point.
You second design provokes usage in the following form:
QRational& r = number.value();
// or
const QRational& r = number.value();
thus the user retains the reference to your inner object. It will be somewhat more difficult to manage in case your number object can be destroyed or moved while r is still there. This does not even depend on whether the const or non-const method is used.
The first design does not expose such problems.

At least in my opinion, if that member acts like an unsigned int (e.g., allows assignment to/from an unsigned int), and you're really sure this class should support direct manipulation of that member (i.e., it should have a "getter" and "setter" at all), then you should at least make access to it clean, rather than requiring other code to be written around that implementation detail. To avoid that, you should define how the type of this object differs from a plain unsigned int, then implement that behavior in a class that defines that type properly and directly.
class QNumber { // bad name--looks like a Qt class name
unsigned int value;
public:
QNumber(unsigned int value = 0) : value(value) {}
QNumber &operator=(unsigned int val) { value = val; return *this; }
operator unsigned int() { return value; }
};
With this, client code can be readable--instead of ugliness like x.SetNumber(2); or x.SetNumber() = 2; you just use x = 2;. This also avoids all sorts of lifetime issues that arise when you let a client get a pointer or reference to the class' internals (which you should generally avoid).

Related

const object or private/const data members (variables) in C++?

We know that const object members cannot be modified once declared but what is the real use of them? We can individually declare variables to be const inside the class or declare them private.
If there is any other significance of const object in C++, then please mention that too.
To answer your question literally:
If you make members of a class const, that applies to every instance of the class, but only to the members that you made const.
If you make an object const, that applies to a single instance of that class, but it does apply to all members of that instance.
const is one of the most elementary subjects in C++, in my opinion. Something that is way too often overlooked.
Generally const has three use cases:
Allowing the compiler to optimize more aggressively
Allowing the compiler to point out our mistakes when we accidentally try to change a const value
Convey intend by specifying that we do not want an object changed
In the case of a const member of a class, we force the object to be initialized during instantiation of the class. Preventing us from accidentally changing it's value in member functions. Which is the big difference to just using a private member variable. We still can accidentally change a private member variable anywhere inside the class.
One of the most useful ways to use const is with parameters:
This can allow major optimization for the compiler, for various reasons that are out of scope of this answer.
And in the case of const references, the compiler can prevent you from accidentally changing the value of that reference.
Most importantly, it allows you to define the signature of your function in a more clarifying way.
I luckily use this once(so far). And i never thought i would need to use a const in a member variable.
class TypeA {
protected:
DataX const* m_data; //get a pointer to a data that shouldn't be modified even inside the class.
public:
TypeA(DataX const* p){
m_data = p;
}
auto& getData(){ return *m_data; } //will return DataX const&
}
For the private member variables, i think they are best for helper-variables in the current class that are really not part of the object logically. Maybe for caching, temporary holder of some data that should be there for a time duration, a counter for an algorithm, etc. And they are only used and should be used in the current class. You don't want other programmers to use them in the derived class because they have a very special use so you hide them in private.
Another example for const member are for constant values aside for enums. I prefer enum over a variable that takes storage but some programmer prefer following on what they used to however you convinced them not to(maybe i'm wrong, and they are really correct, and maybe in the future for some reason the const in the language changed, and then using const might be better.)
class TypeA {
public:
const int HEY_VALUE = 101;
const int YOH_VALUE = 102;
const int HELP_VALUE = 911;
const float MIN_SOMETHING = 0.01;
static const int HELLO_EARTH = 10;
//...
}
I can't find this specific code of mine, but i think i used & instead of const*. I used it like this.
class TypeA {
protected:
DataX& m_data;
public:
TypeA(DataX& p):m_data(p){ //you can only set this once in the constructor
}
auto& getData(){ return m_data; } //will return DataX const&
}
I really prefer using . instead of -> for personal reasons so I really pushing myself to achieve the syntax i want and i came with these weird solutions. It's fun because I discovered that those weird approaches are still valid and achievable in c++.
Update
If there is any other significance of const object in C++, then please mention that too.
Maybe you can const some filler bytes on specific part of the class.
class TypeA {
protected:
const int HEADER_BYTES = 0x00616263;
int m_data1;
int m_data2;
const uint8_t ANOTHER_FILLER_FOR_SOME_REASON = 0xffffffff; //maybe forcing offset address, or alignment, etc.
int m_anotherData;
}
Generally, const keyword is being used to improve readability of the code you are writing.
However, in some cases const can also allow compiler optimizations. Let's see the following code snippet:
int const i = 1;
fun(&i);
printf("%d\n", i);
Here, trying to modify the variable i would cause an Undefined Behaviour. Therefore, the compiler will assume modification won't be even tried so it will pass the value 1 to the printf function.
Same is valid for const data members.

Accessing methods returning copy and reference values respectively [duplicate]

I'm working on learning C++ with Stroustrup's (Programming Principles & Practice Using C++) book. In an exercise we define a simple struct:
template<typename T>
struct S {
explicit S(T v):val{v} { };
T& get();
const T& get() const;
void set(T v);
void read_val(T& v);
T& operator=(const T& t); // deep copy assignment
private:
T val;
};
We're then asked to define a const and a non-const member function to get val.
I was wondering: Is there any case where it makes sense to have non-const get function that returns val?
It seems much cleaner to me that we can't change the value in such situations indirectly. What might be use cases where you need a const and a non-const get function to return a member variable?
Non-const getters?
Getters and setters are merely convention. Instead of providing a getter and a setter, a sometimes used idiom is to provide something along the line of
struct foo {
int val() const { return val_; }
int& val() { return val_; }
private:
int val_;
};
Such that, depending on the constness of the instance you get a reference or a copy:
void bar(const foo& a, foo& b) {
auto x = a.val(); // calls the const method returning an int
b.val() = x; // calls the non-const method returning an int&
};
Whether this is good style in general is a matter of opinion. There are cases where it causes confusion and other cases where this behaviour is just what you would expect (see below).
In any case, it is more important to design the interface of a class according to what the class is supposed to do and how you want to use it rather than blindly following conventions about setters and getters (eg you should give the method a meaningful name that expresses what it does, not just in terms of "pretend to be encapsulated and now provide me access to all your internals via getters", which is what using getters everywhere actually means).
Concrete example
Consider that element access in containers is usually implemented like this. As a toy example:
struct my_array {
int operator[](unsigned i) const { return data[i]; }
int& operator[](unsigned i) { return data[i]; }
private:
int data[10];
};
It is not the containers job to hide the elements from the user (even data could be public). You dont want different methods to access elements depending on whether you want to read or write the element, hence providing a const and a non-const overload makes perfectly sense in this case.
non-const reference from get vs encapsulation
Maybe not that obvious, but it is a bit controversial whether providing getters and setters supports encapsulation or the opposite. While in general this matter is to a large extend opinion based, for getters that return non const references it is not so much about opinions. They do break encapuslation. Consider
struct broken {
void set(int x) {
counter++;
val = x;
}
int& get() { return x; }
int get() const { return x; }
private:
int counter = 0;
int value = 0;
};
This class is broken as the name suggests. Clients can simply grab a reference and the class has no chance to count the number of times the value is modified (as the set suggests). Once you return a non-const reference then regarding encapsulation there is little difference to making the member public. Hence, this is used only for cases where such behaviour is natural (eg container).
PS
Note that your example returns a const T& rather than a value. This is reasonable for template code, where you dont know how expensive a copy is, while for an int you wont gain much by returning a const int& instead of an int. For the sake of clarity I used non-template examples, though for templated code you would probably rather return a const T&.
First let me rephrase your question:
Why have a non-const getter for a member, rather than just making the member public?
Several possible reasons reasons:
1. Easy to instrument
Whoever said the non-const getter needs to be just:
T& get() { return val; }
? it could well be something like:
T& get() {
if (check_for_something_bad()) {
throw std::runtime_error{
"Attempt to mutate val when bad things have happened");
}
return val;
}
However, as #BenVoigt suggests, it is more appropriate to wait until the caller actually tries to mutate the value through the reference before spewing an error.
2. Cultural convention / "the boss said so"
Some organizations enforce coding standards. These coding standards are sometimes authored by people who are possibly overly-defensive. So, you might see something like:
Unless your class is a "plain old data" type, no data members may be public. You may use getter methods for such non-public members as necessary.
and then, even if it makes sense for a specific class to just allow non-const access, it won't happen.
3. Maybe val just isn't there?
You've given an example in which val actually exists in an instance of the class. But actually - it doesn't have to! The get() method could return some sort of a proxy object, which, upon assignment, mutation etc. performs some computation (e.g. storing or retrieving data in a database; or flipping a bit, which itself is not addressable like an object needs to be).
4. Allows changing class internals later without changing user code
Now, reading items 1. or 3, above, you might ask "but my struct S does have val!" or "by my get() doesn't do anything interesting!" - well, true, they don't; but you might want to change this behavior in the future. Without a get(), all of your class' users will need to change their code. With a get(), you only need to make changes to the implementation of struct S.
Now, I don't advocate for this kind of a design approach approach, but some programmers do.
get() is callable by non const objects which are allowed to mutate, you can do:
S r(0);
r.get() = 1;
but if you make r const as const S r(0), the line r.get() = 1 no longer compile, not even to retrieve the value, that's why you need a const version const T& get() const to at least to able to retrieve the value for const objects, doing so allows you do:
const S r(0)
int val = r.get()
The const version of member functions try to be consistent with the constness property of the object the call is made on, i.e if the object is immutable by being const and the member function returns a reference, it may reflect the constness of the caller by returning a const reference, thus preserving the immutability property of the object.
It depends on the purpose of S. If it's some kind of a thin wrapper, it might be appropriate to allow the user to access the underlaying value directly.
One of the real-life examples is std::reference_wrapper.
No. If a getter simply returns a non-const reference to a member, like this:
private:
Object m_member;
public:
Object &getMember() {
return m_member;
}
Then m_member should be public instead, and the accessor is not needed. There is absolutely no point making this member private, and then create an accessor, which gives all access to it.
If you call getMember(), you can store the resulting reference to a pointer/reference, and afterwards, you can do whatever you want with m_member, the enclosing class will know nothing about it. It's the same, as if m_member had been public.
Note, that if getMember() does some additional task (for example, it doesn't just simply return m_member, but lazily constructs it), then getMember() could be useful:
Object &getMember() {
if (!m_member) m_member = new Object;
return *m_member;
}

Reasons for defining non-const 'get' member functions?

I'm working on learning C++ with Stroustrup's (Programming Principles & Practice Using C++) book. In an exercise we define a simple struct:
template<typename T>
struct S {
explicit S(T v):val{v} { };
T& get();
const T& get() const;
void set(T v);
void read_val(T& v);
T& operator=(const T& t); // deep copy assignment
private:
T val;
};
We're then asked to define a const and a non-const member function to get val.
I was wondering: Is there any case where it makes sense to have non-const get function that returns val?
It seems much cleaner to me that we can't change the value in such situations indirectly. What might be use cases where you need a const and a non-const get function to return a member variable?
Non-const getters?
Getters and setters are merely convention. Instead of providing a getter and a setter, a sometimes used idiom is to provide something along the line of
struct foo {
int val() const { return val_; }
int& val() { return val_; }
private:
int val_;
};
Such that, depending on the constness of the instance you get a reference or a copy:
void bar(const foo& a, foo& b) {
auto x = a.val(); // calls the const method returning an int
b.val() = x; // calls the non-const method returning an int&
};
Whether this is good style in general is a matter of opinion. There are cases where it causes confusion and other cases where this behaviour is just what you would expect (see below).
In any case, it is more important to design the interface of a class according to what the class is supposed to do and how you want to use it rather than blindly following conventions about setters and getters (eg you should give the method a meaningful name that expresses what it does, not just in terms of "pretend to be encapsulated and now provide me access to all your internals via getters", which is what using getters everywhere actually means).
Concrete example
Consider that element access in containers is usually implemented like this. As a toy example:
struct my_array {
int operator[](unsigned i) const { return data[i]; }
int& operator[](unsigned i) { return data[i]; }
private:
int data[10];
};
It is not the containers job to hide the elements from the user (even data could be public). You dont want different methods to access elements depending on whether you want to read or write the element, hence providing a const and a non-const overload makes perfectly sense in this case.
non-const reference from get vs encapsulation
Maybe not that obvious, but it is a bit controversial whether providing getters and setters supports encapsulation or the opposite. While in general this matter is to a large extend opinion based, for getters that return non const references it is not so much about opinions. They do break encapuslation. Consider
struct broken {
void set(int x) {
counter++;
val = x;
}
int& get() { return x; }
int get() const { return x; }
private:
int counter = 0;
int value = 0;
};
This class is broken as the name suggests. Clients can simply grab a reference and the class has no chance to count the number of times the value is modified (as the set suggests). Once you return a non-const reference then regarding encapsulation there is little difference to making the member public. Hence, this is used only for cases where such behaviour is natural (eg container).
PS
Note that your example returns a const T& rather than a value. This is reasonable for template code, where you dont know how expensive a copy is, while for an int you wont gain much by returning a const int& instead of an int. For the sake of clarity I used non-template examples, though for templated code you would probably rather return a const T&.
First let me rephrase your question:
Why have a non-const getter for a member, rather than just making the member public?
Several possible reasons reasons:
1. Easy to instrument
Whoever said the non-const getter needs to be just:
T& get() { return val; }
? it could well be something like:
T& get() {
if (check_for_something_bad()) {
throw std::runtime_error{
"Attempt to mutate val when bad things have happened");
}
return val;
}
However, as #BenVoigt suggests, it is more appropriate to wait until the caller actually tries to mutate the value through the reference before spewing an error.
2. Cultural convention / "the boss said so"
Some organizations enforce coding standards. These coding standards are sometimes authored by people who are possibly overly-defensive. So, you might see something like:
Unless your class is a "plain old data" type, no data members may be public. You may use getter methods for such non-public members as necessary.
and then, even if it makes sense for a specific class to just allow non-const access, it won't happen.
3. Maybe val just isn't there?
You've given an example in which val actually exists in an instance of the class. But actually - it doesn't have to! The get() method could return some sort of a proxy object, which, upon assignment, mutation etc. performs some computation (e.g. storing or retrieving data in a database; or flipping a bit, which itself is not addressable like an object needs to be).
4. Allows changing class internals later without changing user code
Now, reading items 1. or 3, above, you might ask "but my struct S does have val!" or "by my get() doesn't do anything interesting!" - well, true, they don't; but you might want to change this behavior in the future. Without a get(), all of your class' users will need to change their code. With a get(), you only need to make changes to the implementation of struct S.
Now, I don't advocate for this kind of a design approach approach, but some programmers do.
get() is callable by non const objects which are allowed to mutate, you can do:
S r(0);
r.get() = 1;
but if you make r const as const S r(0), the line r.get() = 1 no longer compile, not even to retrieve the value, that's why you need a const version const T& get() const to at least to able to retrieve the value for const objects, doing so allows you do:
const S r(0)
int val = r.get()
The const version of member functions try to be consistent with the constness property of the object the call is made on, i.e if the object is immutable by being const and the member function returns a reference, it may reflect the constness of the caller by returning a const reference, thus preserving the immutability property of the object.
It depends on the purpose of S. If it's some kind of a thin wrapper, it might be appropriate to allow the user to access the underlaying value directly.
One of the real-life examples is std::reference_wrapper.
No. If a getter simply returns a non-const reference to a member, like this:
private:
Object m_member;
public:
Object &getMember() {
return m_member;
}
Then m_member should be public instead, and the accessor is not needed. There is absolutely no point making this member private, and then create an accessor, which gives all access to it.
If you call getMember(), you can store the resulting reference to a pointer/reference, and afterwards, you can do whatever you want with m_member, the enclosing class will know nothing about it. It's the same, as if m_member had been public.
Note, that if getMember() does some additional task (for example, it doesn't just simply return m_member, but lazily constructs it), then getMember() could be useful:
Object &getMember() {
if (!m_member) m_member = new Object;
return *m_member;
}

Const reference field as readonly property in C++ class

Is it good to use a const reference field as a readonly getter in C++ classes?
I mean, does this code meet good practices?
class check{
private:
int _x;
public:
const int& x = _x;
void setX(int v){
_x = v;
}
};
It is working very much like C# properties, IMHO, and very easy and clean in class usage code:
check s;
int i;
std::cin >> i;
s.setX(i);
std::cout << s.x << '\n';
s.setX(7);
// s.x = i; // Error
std::cout<<s.x<<'\n';
do this code meet good practices?
Not really, since it introduces unnecessary complexity and space overhead.
Moreover, you wouldn't be able to perform runtime checks and/or assertions, regardless of the value being accessed.
Furthermore, what happens with the lifetime and semantics?
Try assigning one check in your code to another and see what happens. The assignment is ill-formed because the class is non-assignable. You should provide a copy and move constructor to take care of the reference, so that it won't refer to the old object's data member.
Better use _x directly and have a straightforward inline getter function.
PS: C#-like properties in native C++?
Generally, it is not a good practice.
imho, and very easy and clean in class usage code.
Why should that be clearer and easier?
You introduce another variable member (useless overhead). (Generally, the reference will be implemented as an additional member pointer).
It makes the code harder to maintain. You are actually creating dependencies among variable members.
It makes problem in the assignment and in the copy operations. How is copy operation supposed to work?
The "classic" approach is sound clearer by me, e.g.:
class Foo {
public:
void set_num(int value) noexcept { m_num = value; }
int get_num() const noexcept { return m_num; }
void set_string(std::string value) noexcept {
m_str = std::move(value);
}
const std::string& get_string() const noexcept {
return m_str;
}
private:
int m_num;
std::string m_str;
};
From a performances point of view, this approach should be preferred.
Timing complexity: call get_variable on an inline function does not introduce more overhead than your "reference approach". Moreover, it is highly optimizable by the compiler (because of straightforward of the code).
Space complexity: it does not introduce additional data member.
What you propose is in general a bad idea:
You can't implement the property by doing any processing (e.g. with a getter you can store co-ordinates using [x,y] and later decide to change the implementation to use [angle,radius] while keeping the same public interface).
Using a const member variable involves space overhead, and doesn't give you any performance advantage compared with an inline getter.
It's not idiomatic.
Once you've published your class, and other people start using it, you're stuck with it: it's too late to change it to use a method instead.
If your intention with properties is to make the code more succinct, you don't have to use the words "get" and "set" in your function names; that's an old-fashioned practice. You can use the actual name of the "property" as the function name, and you can overload the getter and setter:
class Cheque {
public:
int x() const {
return x_;
}
Cheque & x(int newX) {
x_ = newX;
return *this;
}
private:
int x_;
}
// Usage:
// int amt = myCheque.x(1234);
// Cheque c = Cheque().x(123);
Returning *this as in the above code enables you to use method chaining; a way of implementing the Fluent interface idiom.
When C# compiles a propery it gets compiled into a getter and a setter function.
Here's some C# code that proves this fact:
using System;
namespace Reflect
{
class Program
{
class X
{
public int Prop { get; set; }
}
static void Main(string[] args)
{
var type = typeof(X);
foreach (var method in type.GetMethods())
{
Console.WriteLine(method.Name);
}
Console.ReadKey();
}
}
}
Your output should be:
get_Prop
set_Prop
ToString
Equals
GetHashCode
GetType
get_Prop is the function that implements the getter.
set_Prop is the function that implements the setter.
So even if what you're doing looks similar, it's not the same at all.
Frankly almost everything you could do to try to emulate 'property syntax' in C++ will fall down in one way or another. Most solutions will either cost you memory or it'll have some limitation that makes it more cumbersome than useful.
Just learn to live with getters and setters.
Getters and setters are good practice.
They're short, they're simple, they're flexible, they're typically good candidates for inlining, everyone understands what they do et cetera.

Classes Using their Own Getters/Setters

Let's say I have the following class:
class MyClass
{
private:
int Data;
public:
MyClass(int Init)
{
Data = Init;
}
int GetData() const
{
return Data;
}
};
Now, let's say I want to add a method that checks if Data is equal to zero. There are two ways to accomplish this:
bool DataIsZero() const
{
return Data == 0;
}
Or:
bool DataIsZero() const
{
return GetData() == 0;
}
Which is considered better practice? I can see how just using the variable itself might improve readability, but using the getter might make the code easier to maintain.
I don't really like getters/setters for reasons that I won't go into here. They're covered in other questions. However, since you've asked about them, my answer will assume that I use getters/setters; it will not visit all the possible alternatives.
I'd use the getter, for the maintenance reasons to which you allude. Indeed, the abstraction is half the purpose of having the getter in the first place (along with the slightly tighter access control).
If using the variable is more legible than using the getter, then your getter function name is poor and should be reconsidered.
As an aside, it's best to initialise members, not assign them in your constructor body after the fact. In fact, you have to do that with constants, so you might as well start now and remain consistent:
class MyClass
{
private:
int Data;
public:
MyClass(int Init) : Data(Init) {}
int GetData() const {
return Data;
}
};
See how the constructor has changed.
You should use the getter, because if your class moves to a more complex logic in the getter, then you will be insulated from the change. However, if your class provides a public getter, I'd question the logic of creating this method.
It depends.
The former is sufficient for simple classes.
The latter hides the implementation and can support polymorphism, if the method is virtual.