I make pretty extensive use of PImpl and something that I've found myself waffling on is where exactly to to initialize members of the Pimpl struct. Options are to create a constructor for the Private struct and initialize them there, or to initialize them in the main class's constructor.
myclass.hpp:
class MyClass {
public:
MyClass();
~MyClass();
private:
struct Private; unique_ptr<Private> p;
};
myclass.cpp:
#include "myclass.hpp"
#include <string>
struct MyClass::Private {
int some_var;
std::string a_string;
// Option A
Private() :
some_var {42},
a_string {"foo"}
{}
};
MyClass::MyClass() : p(new MyClass::Private) {
// Option B
p->some_var = 42;
p->a_string = "foo";
}
At present I don't really see a difference between the two other than if I were, for some reason, to want to create new Private objects or copy them around or something, then Option A might be preferable. It also is able to initialize the variables in an initialization list, for what that's worth. But, I find that Option B tends to be more readable and perhaps more maintainable as well. Is there something here I'm not seeing which might tilt the scales one way or the other?
By all means, follow the RAII approach and initialise members in your Private type. If you keep stuff local (and more importantly, at logical places), maintenance will thank you. More importantly, you will be able to have const members, if you use Option A.
If you have to pass values from your MyClass ctor, then do create a proper constructor for Private:
struct MyClass::Private {
int const some_var; // const members work now
std::string a_string;
// Option C
Private(int const some_var, std::string const& a_string) :
some_var {some_var},
a_string {a_string}
{}
};
MyClass::MyClass() : p(new MyClass::Private(42,"foo")) {
}
Otherwise your Private members will be default constructed, only to be overwritten later (which is irrelevant for ints, but what about more complicated types?).
As already noted by #Charles Salvia above, assignment in any of the two constructors incurs some overhead, as the variables are default-constructed before the value is assigned. The amount of this overhead of course strongly depends on the type of your variables.
If you can accept this, I think going for the most readable version is the best. So, if you find assignment in MyClass's constructor the most readable, go for it.
However, take into account that there is no way around an initializer list (for the Private c'tor), namely when your member variables do not have a default constructor or when you use references or constants.
You might want to decide this from case to case, but "always" using initializer lists will keep things consistent and future-proof for newly added data members.
Related
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;
}
I'm a Java developer trying to pick up C++. Is it okay to use a setter inside a constructor in order to reuse the sanity checks the setter provides?
For example:
#include <stdexcept>
using namespace std;
class Test {
private:
int foo;
void setFoo(int foo) {
if (foo < 42) {
throw invalid_argument{"Foo < 42."};
}
this->foo = foo;
}
public:
Test(int foo) {
setFoo(foo);
};
};
Yes, it is recommended to do this, basically for the reason you already mentioned.
On the other hand you should ask yourself if you need the setter at all and not directly implement the checks inside the constructor. The reason I am writing this is that setters in general result in mutable state which has many disadvantages as opposed to immutable classes. However sometimes they are required.
Another recommendation: If your class variable is an object and you can modify the constructor of this object, you could put the check into the constructor of this object:
class MyFoo {
public:
MyFoo(int value) {
if (value < 42) {
throw invalid_argument{"Foo < 42."};
}
v = value;
}
private:
int v;
}
This will enable you to use an initialization list in the constructor of your Test class:
Test(int foo) : foo(foo) {}
However, now the check is a property of the class of the variable and no longer one of the owning class.
Yes you can. It's fine as long as your setters are not virtual, because it's inheritance hierarchy in calling right functions as the "this" ptr is not ready yet.
Here is Herb Sutter GOTW on this matter: http://www.gotw.ca/gotw/066.htm
Yes, that's fine as long as it makes sense to have a setter for a particular member variable (have some logic that can't be checked by assignment only for example) . In this example, setFoo could've just taken an unsigned int and the caller would know not to pass negative values. Which in turn could eliminate the check and thus the need for a setter. For more elaborate checks, a setter and usage of that setter in the constructor is just fine.
Short answer: Yes. In fact, your example works.
Long answer: But it is not a good practice. Al least, you have to take care.
In general, a set function works with a constructed object. It is supposed that the invariant of the class holds. The functions in a class are implemented considering the invariant is true.
If you want other functions to be used in a constructor, you would have to write some code. For example, to create an empty object.
For example, if in your class you change setFoo in the future (let's say setFoo changes the member foo only it is larger) you example stop working.
This is okay.
The only situation you cannot call member function is when the base classes are not constructed yet.
can member functions be used to initialize member variables in an initialization list?
I know this doesn't fit your situation. Its just for the sake of completeness:
When you are simply settings member values (without checks like yours in setFoo) it is recommended to use initialization lists in the constructor. This prevents members being "initialized" 2 times: 1. with their default value, 2. with the value that you passed into the constructor.
class Test {
private:
int foo_;
public:
Test(int foo)
: foo_(foo)
{ };
};
My C++ project is getting huge. In some situations I'm passing arguments by reference just for my own convenience, in some I don't. Here's an example:
struct foo{
foo(int &member){
this->member = &member;
}
private:
int *member;
};
I'm using this pattern when I don't want to create two instances of the int variable. I don't have to implement the get or modify methods to manipulate its value. Instead I can change the variable without even accessing the foo object. However sometimes I'm using a different way of managing the member variables:
struct foo{
foo(int member){
this->member = member;
}
void modify_member(){
this->member = 6;
}
int get_member(){
return this->member;
}
private:
int member;
};
I'm not sure whether mixing these two methods of managing members in the same struct is a good practice. Should I normalize it? So for example EVERY function in the given struct will be using the "pass by value" method?
Your first case is a recipe for disaster. You'll end up with dangling pointers and a truck load of undefined behaviour.
Your second case is a poor attempt at encapsulation. There's no need for it. Just use the int. That will reduce the size of your code base.
Code should be simple to read and simple to change, that is in a way that does not break your program. Example one will lead to code, where you can hardly tell where foo instances are altered. Not to forget all the others issues mentioned already.
Example two is okay. In general, providing getters and setters let you add constraints later such as checking value ranges. So I recommend using them, unless you have good reasons not to do so. It also makes refactoring easier.
When passing parameters in a function: As a rule of thumb use pass by value in case of primitive types: int, double, etc.. When passing objects use constant References foo(const MyClass &myClass).
class MyClass {
public:
MyClass(const MyOtherClass &member1, int member2){
this->member1 = member1;
this->member1 = member1;
}
// other functions, getters, setters omitted...
private:
MyOtherClass member1;
int member2;
};
This may be a silly question, but still I'm a bit curious...
Recently I was working on one of my former colleague projects, and I've noticed that he really loved to use something like this:
int foo(7);
instead of:
int foo = 7;
Is this a normal/good way to do in C++ language?
Is there some kind of benefits to it? (Or is this just some silly programming style that he was into..?)
This really reminds me a bit of a good way how class member variables can be assigned in the class constructor... something like this:
class MyClass
{
public:
MyClass(int foo) : mFoo(foo)
{ }
private:
int mFoo;
};
instead of this:
class MyClass
{
public:
MyClass(int foo)
{
mFoo = foo;
}
private:
int mFoo;
};
For basic types there's no difference. Use whichever is consistent with the existing code and looks more natural to you.
Otherwise,
A a(x);
performs direct initialization, and
A a = x;
performs copy initialization.
The second part is a member initializer list, there's a bunch of Q&As about it on StackOverflow.
Both are valid. For builtin types they do the same thing; for class types there is a subtle difference.
MyClass m(7); // uses MyClass(int)
MyClass n = 3; // uses MyClass(int) to create a temporary object,
// then uses MyClass(const MyClass&) to copy the
// temporary object into n
The obvious implication is that if MyClass has no copy constructor, or it has one but it isn't accessible, the attempted construction fails. If the construction would succeed, the compiler is allowed to skip the copy constructor and use MyClass(int) directly.
All the answers above are correct. Just add that to it that C++11 supports another way, a generic one as they say to initialize variables.
int a = {2} ;
or
int a {2} ;
Several other good answers point out the difference between constructing "in place" (ClassType v(<constructor args>)) and creating a temporary object and using the copy constructor to copy it (ClassType v = <constructor arg>). Two additional points need to be made, I think. First, the second form obviously has only a single argument, so if your constructor takes more than one argument, you should prefer the first form (yes, there are ways around that, but I think the direct construction is more concise and readable - but, as has been pointed out, that's a personal preferance).
Secondly, the form you use matters if your copy constructor does something significantly different than your standard constructor. This won't be the case most of the time, and some will argue that it's a bad idea to do so, but the language does allow for this to be the case (all surprises you end up dealing with because of it, though, are your own fault).
It's a C++ style of initializing variables - C++ added it for fundamental types so the same form could be used for fundamental and user-defined types. this can be very important for template code that's intended to be instantiated for either kind of type.
Whether you like to use it for normal initialization of fundamental types is a style preference.
Note that C++11 also adds the uniform initialization syntax which allows the same style of initialization to be used for all types - even aggregates like POD structs and arrays (though user defined types may need to have a new type of constructor that takes an initialization list to allow the uniform syntax to be used with them).
Yours is not a silly question at all as things are not as simple as they may seem. Suppose you have:
class A {
public:
A() {}
};
and
class B {
public:
class B(A const &) {}
};
Writing
B b = B(A());
Requires that B's copy constructor be accessible. Writing
B b = A();
Requires also that B's converting constructor B(A const &) be not declared explicit. On the other hand if you write
A a;
B b(a);
all is well, but if you write
B b(A());
This is interpreted by the compiler as the declaration of a function b that takes a nameless argument which is a parameterless function returning A, resulting in mysterious bugs. This is known as C++'s most vexing parse.
I prefer using the parenthetical style...though I always use a space to distinguish from function or method calls, on which I don't use a space:
int foo (7); // initialization
myVector.push_back(7); // method call
One of my reasons for preferring using this across the board for initialization is because it helps remind people that it is not an assignment. Hence overloads to the assignment operator will not apply:
#include <iostream>
class Bar {
private:
int value;
public:
Bar (int value) : value (value) {
std::cout << "code path A" << "\n";
}
Bar& operator=(int right) {
value = right;
std::cout << "code path B" << "\n";
return *this;
}
};
int main() {
Bar b = 7;
b = 7;
return 0;
}
The output is:
code path A
code path B
It feels like the presence of the equals sign obscures the difference. Even if it's "common knowledge" I like to make initialization look notably different than assignment, since we are able to do so.
It's just the syntax for initialization of something :-
SomeClass data(12, 134);
That looks reasonable, but
int data(123);
Looks strange but they are the same syntax.
I have a class:
class A
{
private:
ComplexClass member1;
public:
getMember1(){return member1;};
};
and I have an implementation that, for code simplification (more easily understandable), needs to retrieve that member1 to work with it. The first thing that would come to my mind would be:
ComplexClass *myComplexClass = &getMember1();
myComplexClass.getSomething();
myComplexClass.getSomethingElse();
etc.
which is obviously not correct since I'm retrieving a pointer from a new object and not from member1 (and gets a compiler warning).
My question is: what is the best design to do things like this? How do I keep encapsulation and yet facilitate the access of a members using a pointer to it? (I only want to read from member1, not to write on it).
Should I make a
ComplexClass *getPointerToMember1()
inside the class A?
A const reference will keep them from editing. In my opinion, it makes your intention clearer than a const pointer.
class A
{
private:
ComplexClass member1;
public:
const ComplexClass &getMember1(){return member1;};
};
You're returning the member by value which makes a copy of the ComplexClass member. Thus you aren't working on the actual member when you call the subsequent methods (and what the compiler is telling you).
I think the more idiomatic C++ approach that helps maintain encapsulation and reduces coupling is to create an algorithmic member:
A::doStuff()
{
member1.getSomething();
member1.getSomethignElse();
}
This way anyone that uses class A doesn't care that the implementation uses a ComplexClass but instead just knows that they can tell A to do some work and it will get done in the best possible way.
EDIT for comment: In that case, I would suggest creating methods in A that get the values from ComplexClass (again to hide your implementation). If that's not suitable, then you could return the implementation by const reference: const ComplexClass& getMember1() const { return member1; }