First, my latest coding is Java, and I do not want to "write Java in C++".
Here's the deal, I have to create an immutable class. It's fairly simple. The only issue is that getting the initial values is some work. So I cannot simply call initializes to initialize my members.
So what's the best way of creating such a class? And how can I expose my immutable / final properties to the outside world in C++ standards?
here's a sample class:
class Msg {
private:
int _rec_num;
int _seq;
string text;
public:
Msg(const char* buffer) {
// parse the buffer and get our member here...
// ... lots of code
}
// does this look like proper C++?
int get_rec_num() { return _rec_num; }
};
C++ offers some nice mechanisms to make your class immutable. What you must do is:
declare all your public (and maybe protected) methods const
declare (but not define) operator= as private
This will ensure that your objects cannot be modified after they have been created. Now, you can provide access to your now immutable data members anyway you want, using const methods. Your example looks right, provided that you make it const:
int get_rec_num() const { return _rec_num; }
EDIT: Since C++11 you can explicitly delete operator=, rather than just leave it undefined. This explicitly instructs the compiler to not define a default copy assignment operator:
Msg& operator=(const Msg&) = delete;
I'd mark your immutable member as 'const', and assign it a value in your constructor initializer list.
I'd also parse your buffer outside of the class, and pass in the string to the constructor.
Something like this:
class Msg {
private:
int _rec_num;
int _seq;
const std::string text;
public:
Msg(const std::string& str) :
text(str)
{
}
// does this look like proper C++?
int get_rec_num() const { return _rec_num; }
};
// parse the buffer and get our parameter somewhere else
NB:
You should make any member functions that do not change the state of your class internals as 'const'; as this will allow you to call them with const objects.
You should avoid inluding a using std::string in header files; as anyone who includes your header has this 'using' forced upon them.
You're on the right track -- use getters for everything, and without any setters, your class is effectively immutable.
Don't forget some of the corner cases though -- you might want to declare the operator=() method as private and not implement it so someone can't override the object with the default compiler generated assignment operator, etc.
// does this look like proper C++?
int get_rec_num() { return _rec_num; }
You should use
int get_rec_num() const { return _rec_num; }
(see the const which allows to call the member on const objects).
To make a variable immutable you have to use the const key word eg const int _rec_num. Const variables can only be initialised through an initialisation list, which gets called before any code in the constructor. This means that you cannot do any processing in the constructor which sets the const member variables.
You have two ways round this, first you can create another internal class which takes in a buffer and parses it into your variables. Put a const version of this into your MSG class and put this in the initialisation list:
class MsgInner
{
public:
int _rec_num;
Msg(const char* buffer) {
// Your parsing code
}
};
class Msg
{
public:
const MsgInner msg;
Msg(const char* buffer) : msg(buffer)
{ // any other code }
};
This is perhaps not so 'standard', but it's another perspective. Otherwise you can also do it as the other answers have suggested with get methods.
On Finalizers
There is none, you have to emulate it. Either by using a cleanup function or by having all your resources encapsulted in RAII classes. The compiler will place static machinery in your application to call destructors on your RAII classes --i.e., when they go out of scope the resources get released through the destructor.
On Immutability and Initialization
Generally if something is immutable and const-correct the class will have all of its members as const and the only time you get to "write" to them is when the class is initialized. However in your case that might not be possible.
I suggest you gather all your resources and initialize the class (via a non-default constructor with const members) once you have them. The other alternative (which I do not abide) is to have a mutator function that "claims" to be const correct but writes to the const values for a one-time post construction initialization.
First of all, it is possible to initialize the members efficiently and at construction time even if they were declared as const (which is neither necessary nor recommended).
I would still suggest that you split this class into two separate classes (pseudo-code):
// Msg: pure data object; copy constructible but not modifiable.
class Msg
{
public:
Msg(int rec_num, ...)
: rec_num_(rec_num)
...
{}
int rec_num() const
{ return rec_num_; }
...
private:
// prevent copying
Msg& operator=(Msg const&);
private:
int rec_num_;
};
// MsgParser: responsible for parsing the buffer and
// manufacturing Msg's.
class MsgParser
{
public:
static Msg Parse(char const* buffer)
{
... parse ...
return Msg(...);
}
};
// Usage
Msg const msg = MsgParser::Parse(buffer);
This also nicely separates the concerns of holding and parsing the data into separate classes.
Related
In my company, we generate code from XML. The code generator generates header files that contain Messages, and each message contains only data. NOTE we don't do any validation while setting or returning data; also, we don't have to take care of the state, i.e., data x and data in a message are independent; if x is changed, we don't need to change the state of y.
Current header file
class somemessage
{
private:
Field _field;
.......
public:
Field& getfield(){...}
const Field& getfield() const {...}
void setfield(const Field& field){....}
} ;
Do we still need data hiding here if it's only data? Do we require getter and setters in these headers, or can se make it simple as following.
struct somemessage
{
Field field;
};
We can make the message read-only when required using const as following.
void message_consumer(const somemessage& message)
{
message.field = somevalue; // compilation error
}
What are the disadvantages of this approach, and what are the advantages of using accessors and mutators?
If you have the following pattern:
class A {
public:
void SetFoo(const Foo& newFoo) {
f = newFoo;
}
const Foo& GetFoo() const {
return f;
}
protected:
private:
Foo f;
};
That is, you have a getter/setter pair and all they do is have a single return statement and a single assignment expression, then there's no need for the data member to be private and instead just make the data member public and remove the getter/setter pair.
class A {
public:
Foo f;
protected:
private:
};
If your getters/setters do anything else, or are in any way more complicated, then yes, having a getter/setter pair is fine.
In terms of using a struct versus a class, I go with struct if the type is strictly only data; no functions, no constructors. If for whatever reason the data type needs functions, then it should be declared as a class.
Writing a getter like this:
Field& getfield(){...}
is not encapsulation. A user can do this:
Field& decapsulated = x.getField();
and now they have a reference to the private member that they can use to do what they like. All checking and bookkeeping in the setter is futile, because the user does not need it to modify the private member:
decapsulated = some_other_field;
Proper encapsulation has advantages. Though plain old structs with only public members have their place as well. If however all you do is writing boilerplate that does not encapsulate the data, you can leave away the boilerplate. Eventually it is up to you to decide what to use. Encapsulation has lots of advantages, but it is not a must.
Getters returning non-const references can be useful as convenience methods. They can provide easy means for the user to access the class data. Compare for example to std::vector::operator[] or std::vector::at(). Though one should not confuse that with data encapsulation.
Let's say we have this simple class
struct MyClass {
const std::string &getString() const & {
return m_string;
}
std::string getString() && {
return std::move(m_string);
}
private:
std::string m_string;
};
As we can see, the m_string acts as a non mutable variable in the sense that we cannot modify it.
This structure also preserve the fact that if we move one instance of MyClass to another, the m_string attribute will be moved as well.
Now, we are going to try to refactor the prior structure :
struct MyClass {
std::string m_string;
};
Here, we keeps the fact that we can access it or move it, but we lose the "immutability"... So I tried to write it like that :
struct MyClass {
const std::string m_string;
};
Here we get the immutability thing, however, we lose the potential optimization when we move the object...
So, is it possible to have a behavior similar to the first code, without writing all the getter?
EDIT: the std::string is just for example, but the idea must be usable with all kind of objects
So, is it possible to have a behavior similar to the first code, without writing all the getter?
I can't think of any.
Having said that, the overhead of writing getters and setters for member variables is not such a big burden that I would spend too much time thinking about it.
However, there are some who think that getters and setters of member variables don't add enough protection to a class to even worry about them. If you subscribe to that line of thinking, you can get rid of the getters and setters altogether.
I have used the "no getters and setters" principle for containers of data enough times that I find it natural in many use cases.
You can implement this behavior using a template wrapper type. It seems you want a type that works well with copy and move construction and assignment, but which only provides const access to the wrapped object. All you should need is a wrapper with a forwarding constructor, an implicit conversion operator and dereferencing operators (to force the conversion when implicit conversion doesn't work) :
template<class T>
class immutable
{
public:
template<class ... A>
immutable(A&&... args) : member(std::forward<A>(args)...) {}
public:
operator const T &() const { return member; }
const T & operator*() const { return member; }
const T * operator->() const { return &member; }
private:
T member;
};
This will work well with compiler generated copy and move construction and assignment. The solution is not 100% transparent however. The wrapper will implicitly convert to a reference to the wrapped type, if the context allows it :
#include <string>
struct foo
{
immutable<std::string> s;
};
void test(const std::string &) {}
int main()
{
foo f;
test(f.s); // Converts implicitly
}
But it will need an extra dereference to force the conversion in contexts where implicit conversion will not work :
int main()
{
foo f;
// std::cout << f.s; // Doesn't work
std::cout << *(f.s); // Dereference instead
// f.s.size(); // Doesn't work
f.s->size(); // Dereference instead
}
There was a proposal to add overloading of the . operator, which would allow most cases to work as intended, without a dereferencing. But I'm not sure what the current state of the proposal is.
The solution is to use std::shared_ptr<const std::string>. A shared pointer to a immutable object has value semantic. Copy-on-write can be achieved using shared_ptr::unique(). See Sean Parent presentation 47:46 https://youtu.be/QGcVXgEVMJg.
If only you are willing to declare the copy and defuslt ctor as =default and define the move ctor with const_cast cheat.
MyClass::Myclass()=default;
MyClass::Myclass(Myclass const&)=default;
MyClass::Myclass(Myclass && m)
: m_string{std::move(const_cast<std::string&>(m.m_string))}{};
Let's assume I have a class A looking like that:
class A {
public:
public A(bool someFlag, Params someParams);
private:
vector<string> texts;
}
I would like to extract the logic of initializing the texts member field.
I came up with 2 ideas:
First idea - static, private member functions that would return the desired vectors of texts.
A::A(bool someFlag, Params someParams) {
if (someFlag)
texts = createSomeTexts(someParams);
else
texts = createOtherTexts(someParams);
}
Second idea - private member functions that would assign the desired vectors of texts to the class members by themselves.
A::A(bool someFlag, Params someParams) {
if (someFlag)
createAndAssignSomeTexts(someParams);
else
createAndAssignOtherTexts(someParams);
}
Of course both versions do the job correctly, but I wonder what is the advised approach to theese situations. Also, if the approach should change if member initalization requires more parameters (especially ones that are stored in the class as members as well).
You should strive to initialize your data member, not assign to them in the constructor body. Both versions you showed cause default construction of the std::vector<std::string> instance, and assign to it later. Hence, I'd suggest this:
A::A(bool someFlag, const Params& someParams) :
texts(someFlag ? createSomeTexts(someParams) : createOtherTexts(someParams))
{}
or, more readable, let createSomeTexts handle the flag, too:
A::A(bool someFlag, const Params& someParams) :
texts(createSomeTexts(someFlag, someParams))
{}
Make createSomeTexts a member function if it needs to access other data members (make sure they're declared before the texts member and properly initialized - as #Scheff pointed out, this is unlikely to be a good idea, though). Otherwise, make it a free function (see here why this is preferrable). Once createSomeTexts is a free function, you could equally well construct the object like this:
std::vector<std::string> stringsToInject = createSomeText(/* Some flags.... */);
A instance(stringsToInject); // A's ctor updated to make this work
which could further separate concerns as the constructor of A takes care of initializing the data members, while the logic to create the initialization data is located somewhere else.
I would use case 1 because the functions createSomeTexts and createOtherTexts do not alter any class variables. That means these functions can be unit tested.
It is better not to use global variables and if you must, not to alter them from the global scope (this->) but to pass them by reference or as a pointer to your function.
This way you can pass stubs in your code and write test cases.
Also, Params should be a const reference:
class A {
public:
public A(const bool someFlag, const Params &someParams);
private:
vector<string> texts;
}
Let Memeber be a class and let's assume I have no idea if it supports or need move semantics. For all intents and purposes let's say it isn't even specified/written yet. Which case of the SetMember functions should I implement in an Outer class, which has Member as a member?
If Member would not support move, I would do this:
class Member {
public:
Member(Member&&) = delete;
Member& operator=(Member&&) = delete;
};
class Outer {
Member m_member;
public:
void SetMember(const Member& o) { m_member = o.m_member; } // makes a copy
};
And if Member would support move, I would do this:
class Member {
public:
Member(Member&&);
Member& operator=(Member&&);
};
class Outer {
Member m_member;
public:
void SetMember(Member o) { m_member = std::move(o.m_member); } // makes a copy if needed
};
But since I do not know if it has move or not, do I need to implement both? Like this:
class Outer {
Member m_member;
public:
void SetMember(const Member& o) { m_member = o.m_member; } // makes a copy
void SetMember(Member&& o) { m_member = std::move(o.m_member); } // makes no copy
};
Or should I do this?
class Outer {
Member m_member;
public:
template <class T>
void SetMember(T&& o) { m_member = std::forward<T>(o.m_member); }
};
Why I'm not happy with these two solutions:
In the first solution I see code duplication, which is only needed because I don't know some implementation details of Member namely if it supports move or not.
The second solution leaves me with compilation errors instead of intelli sense errors whenever I try to use SetMember on a wrong type. Also I need a template just because some implementation details of Member.
What's the clean way to handle this situation?
As far as I know passing by value in setters is no longer recommended. At least in case of std::strings when setter is called multiple times, it is highly probable, that the destination variable has enough memory reserved for new value and it's cheaper to just copy the content into already allocated string then create a temporary string and move it.
So no matter if the type is moveable or not it is recommended to pass by const reference and make a copy inside of a setter. If later profiling shows that a temporary is used often as an argument and the cost of copying makes it worth optimizing, an overload for rvalue reference may be added.
See also https://stackoverflow.com/a/26286741/113662
There are two methos for implementing get/set.
Method 1:
Define get and set separately.
class my_class
{
// ...
};
class main_class
{
public:
my_class get_data() const
{
return m_data;
}
void set_data(my_class value)
{
m_data = value;
}
private:
my_class m_data;
};
Note: In this method get is fast enough: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value
And another method is (Method 2):
Define two get bodies, First const and another non const.
class my_class
{
// ...
};
class main_class
{
public:
const my_class& get_data() const
{
return m_data;
}
my_class& get_data() // Works like set.
{
return m_data;
}
private:
my_class m_data;
};
Using these methods:
void main()
{
main_class cls;
// For method 1.
my_class data;
data = cls.get_data();
cls.set_data(data);
// For method 2.
const my_class data1;
my_class data2;
data1 = cls.get_data(); // const get invoked.
cls.get_data() = data2; // Like set beacuase non const get invoked.
}
My question which of these methods for implementing get/set is better?
Do you know a better method?
Edit:
For answers that believe Method 1 is better, what do you say in below situation:
void main()
{
main_class cls;
// For method 1.
cls.get_data().do_something_else(); // Not effictive for cls, because data losts.
// For method 2.
cls.get_data().do_something_else(); // Effictive for cls.
}
You should always use a reference for any custom classes to pass just the address not the value class. You should also avoid passing back a non-const reference for editing. See below for my recommendations.
class my_class
{
// ...
};
class main_class
{
public:
const my_class & get_data() const
{
return m_data;
}
void set_data(const my_class & data)
{
m_data = data;
}
private:
my_class m_data;
};
I know this won't be a popular answer with C++ purists and before I learned Python, and Ruby I wouldn't have broached the possibility... but... Since the getter and setter you provided doesn't do range checking or special calculations why not make the member public?
class main_class
{
public:
my_class my_data;
}
Sure, you'll lose the const on the getter and won't be guaranteed protection, but you're not guaranteed that anyway because you provide a set function, which modifies the member.
The second one is very bad as it abandons the encapsulation: you can as well just make the corresponding field public, anyone could access it without your object knowing about it. You cannot perform range checks or status updates based on the data being changed etc.
The second one would be a pretty bad choice. The reason for having setters is to be able to control how the member variable is modified by the user. If you just give the user a reference to your member, you lose all control.
So you're pretty much left with the first method. Below are two variations that you might or might not like:
// First Variation
// ---------------
// In this one both the setter and the getter have the same name
// (which is the same as the member they control). To get a
// variable you do `int i = foo.var()` and to set it you do
// `foo.var(6)`.
class Some
{
public:
int var() const {
return var_;
}
void var(int v) {
var_ = v;
}
private:
int var_;
};
// Second Variation
// ----------------
// You can also make the setter return a reference to `this`.
// This allows you to chain setters, which can _sometimes_ be
// more readable but it also has a few disadvantages.
class Employee
{
public:
Employee& salary(double dollars) {
salary_ = dollars;
return *this;
}
Employee& name(const string& n) {
name_ = n;
return *this;
}
private:
double salary_;
std::string name_;
};
// You can now do this...
Employee emp;
emp.name("John Barlick").salary(500.00);
// ... But this can become quite ugly if you chain a large amount
// of setters (you'd then probably have to break the lines in
// order to keep the code readable). It also is (technically)
// less efficient.
// In case you have lots of setters you could probably do this:
// emp.name("John Barlick")
// .salary(500.00)
// .some(787);
// .another('g');
Usually getters/setters are defined:
const my_class& get_data() const
{
return m_data;
}
void set_data(const my_class& _data)
{
m_data = _data;
}
First of all, I think this is not very effective
void set_data(my_class value)
{
m_data = value;
}
You should probably pass by reference
void set_data(const my_class& value)
{
m_data = value;
}
As to which method you should choose, think this way - In your second method you return a reference to your internal object and the user is absolutely free to do anything with it. With the first method, you can control what the user can or cannot do.
While standard getters and settters like method 1 may provide "encapsulation", unless these functions are inlined in a header, they are adding a lot of overhead. For instance, in a tight loop, even if you used references rather than pass-by-value (which then requires a costly memory copy operation), constantly having to add about eight instructions in x86 for every call to a getter/setter in order to setup up its activation record on the stack as well as the function's prologue and epilogue is using up valuable CPU time, and really hurts performance. Since you're getter and setters aren't doing much, you really don't need them.
Method 2 is actually what a number of STL containers do, like std::vector with the operator[], where you overload the same function, but define one for constant operations, and another for non-constant operations ... but again, you're adding unnecessary overhead when you could just publicly access the data member (i.e., it's not like you're some underlying pointers and other memory-managed data-members from us like an STL container). If the function you're passing it to requires a constant reference, it's not going to change the member anyways, so there's really no need to create an interface like this unless you are trying to make a common interface for accessing a member across a host of classes. And if you're doing that, then you should look into a pure virtual base class to define the common interface.
IMHO the second method looks very awkward.