PIMPL idiom clarification [closed] - c++

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
While trying to remove all implementation details from a header file I decide to use and try out PIMPL idiom. The majority if not all examples, e.g. cppreference, I've seen use levels of indirection which reason I can't understand besides encapsulation. The examples always come with this flavor pattern.
Typical
//A.hpp
class A
{
public:
A(int);
//More non-static class methods
void set(int);
private:
struct a_impl;
std::unique_ptr<struct a_impl> pimpl;
};
//A.cpp
struct A::a_impl
{
private:
int i;
public:
a_impl(int i) : i{i}{}
//More non-static implementation class methods
void set(int i) {this->i = i;}
};
A::A(int i) : std::make_unique<struct a_impl>(i) {}
A::set(int i) {pimpl->set(i);} //????
A:://More indirect calls to non-static member functions through pointer
At certain point I start wondering why do I need all this level of complexity and indirection if we are talking about implementation. Why not something simplest without all those indirect calls.
Why not ?
//A.hpp
class A
{
public:
A(int);
//.....
void set(int);
private:
struct a_impl;
std::unique_ptr<struct a_impl> pimpl;
};
//A.cpp
struct A::a_impl
{
int i;
}
A::A(int i) : std::make_unique<struct a_impl>() { pimpl->i = i; }
A::set(int i) { pimpl->i = i; } //!!!!
What I would like to clarify:
1-Are all this samples presented this way just for a matter of education and good encapsulation practices?
2-Is there any other good reason I'm missing to add this level of complexity and overhead besides question 1?
3-Or what I put out as an alternative isn't PIMPL idiom?

Your own approach and the one you compare it against are just two different flavors of the idiom. Herb Sutter listed them, and more, in GotW #100:
What parts of the class should go into the impl object? Some potential
options include:
put all private data (but not functions) into impl;
put all private members into impl;
put all private and protected members into impl;
put all private nonvirtual members into impl;
put everything into impl, and write the public class itself as only the public interface, each implemented as a simple forwarding function
(a handle/body variant).
Each has its own strong and weak points. For the case you study, your approach does seem better. For other cases, a pimpl with behavior and not just state may be more appropriate. There isn't really a one size fits all.

Related

Private getters and setters [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I am still new to C++ and OOP programming, and I was just wondering about something curious.
I have a class let's name it Foo, with some private members.
My question is: the Foo objects don't "pass data" to other objects during their lifespan. They receive data, do things, and save new data to file. That means, only Foo objects will access Foo private members.
Is it wrong to implement private getters and setters?
Or should I use direct access?
Pseudo code below:
Is this okay?
class foo
{
private:
string a;
string b;
string c;
void setA(string A){this->a=A;}
string getA()const{return this->a;
void setB(string B){this->b=B;}
string getB()const{return this->b;
void setC(string C){this->c=C;}
string getC()const{return this->b;
public:
//many omitted methods//
void Method(); //<-- this method does things and calls private getters and setters to modify private members
}
In main:
{
Foo obj=....;
obj.Method();
}
Or should I:
class foo
{
private:
string a;
string b;
string c;
public:
//many omitted methods//
void Method();
}
void foo::method()
{
string s1;
//initialize s1;
this->a=s1; //operation example
std::cout<<"A equals: "<< this->a;
}
Not sure if I explained my concerns in simple way.
Thank you in advance for your replies and help.
Writing private "getters" and "setters" is pointless, unless you are exploiting polymorphism in some funny way.
Setting up your member variables via a constructor is the best thing to do, and making the members const prevents their unintentional modification.
Avoid "setters" whenever possible regardless of their accessibility as they do little more than circumvent encapsulation.
I'm not the most experienced C++ developer, but from my point of view, using direct access is not a bad practice and it will require less time to write.
On the other hand, having such members in your interface makes it clear that only the Foo objects could read Foo's private members, so both ways are acceptable.
The main point of having getters and setters is controlling access to the class members in a flexible and extensible way. You don't get anything from creating getters and setters if you know they will never be used by external clients of the class, so I would advice to not write them at all.
They will only clutter your source files and make your code harder to read.
By they way, you don't need to use this everytime you want to access a member:
class foo {
private:
string a;
string b;
string c;
public:
//many omitted methods//
void Method();
}
void foo::method() {
string s1;
a=s1;
std::cout<<"A equals: "<< a;
}

Design of c++ class: common use of class members in other class members; Small interface vs small classes [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Say I have a class A with some member attributes. A also has a vector with objects of class B (std::vector<B>). Those B objects need some (let's say 5) of the attributes of A. I see two ways of handling this:
1) Let B have references to those attributes, and assign them in B's constructor.
2) Let B only have a reference to the A object, and get the attributes via public getAttributeXYZ() functions.
I can see that solution 1) technically knows less about A, therefore it's better because it couldn't for example call some wrong A function. But I feel like 2) is much cleaner, since the constructor is way smaller and the B class has much fewer (reference-) attributes itself. Is there a general better way or does it depend on the details?
Context: In my program, those members of A are classes for texture management, text drawing etc that can be shared by all of the B objects.
In this case, you can have your cake and eat it too, by giving the Bs access to only the relevant subset of A. There are multiple ways you could go about this.
One, gather the attributes in a dedicated class:
struct A
{
struct SharedData
{
int data;
// ...
};
A();
private:
SharedData sharedData;
std::vector<B> bs;
// other data here
};
struct B
{
B(A::SharedData *data) : data{data} {}
private:
A::SharedData *data;
};
A::A() : bs{B{&sharedData}} {}
Two, give A a dedicated interface to access these attributes:
struct SharedDataInterface
{
virtual int getData() const = 0;
};
struct A : SharedDataInterface
{
int getData() override { return sharedData; }
A();
private:
std::vector<B> bs;
int sharedData;
// other data here
};
struct B
{
B(SharedDataInterface *data) : data{data} {}
private:
SharedDataInterface *data;
};
A::A() : bs{B{this}} {}
I'm sure other variations on this topic are also possible.

C++11, is default member construction a good thing? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
Since C++11 we can default construct our variables in a class, like this:
class Foo{
private:
int bar = 0;
};
I've very rarely seen someone using this feature
Is this a good practice ?
This is a style question, but there are some considerations that are hopefully universal:
If all constructors of your class have to initialize a member the same way, because the initial value is in some profound way part of the invariants of the class, then it is both more readable and self-documenting and also shorter to use the inline initializer, and the deduplication removes a source of errors if you ever need to change the initial value.
Otherwise, if different constructors supply different initial values, then you shouldn't have an inline initializer, even though that's technically permitted.
I dont see any bad practices in this approach. This is allowed even in Higher level languages like Java. It reduces lines of code inside constructor.
The only big disadvantage I see is that it may lead people to expose more implementation details than necessary in class definitions. Currently, if you initialize a member in MyClass.cpp, then you can easily change the value later on. If you initialize the member in MyClass.h, then a lot of recompilation could be necessary if you later change the value.
In Java, you don't have this kind of separation between header and implementation, so the situation cannot be compared to C++.
C++11 allows non-static data members to be initialized in-class.
This can often save some typing. Consider the following example:
class Foo {
public:
Foo() : a_{5}, b_{7}, s_{"Foo"}, bar_{"Test"} {}
Foo(int x) : a_{x}, b_{7}, s_{"Foo"}, bar_{"Test"} {}
Foo(double d) : a_{5}, b_{g(d)}, s_{"Foo"}, bar_{"Test"} {}
int someFunc();
private:
int a_;
int b_;
std::string s_;
Bar bar_;
};
Using in-class initialization will IMHO make the code more readable.
class Foo {
public:
Foo() = default;
Foo(int x) : a_{x} {} // Initialization list overrides in-class initialization.
Foo(double d) : b_{g(d)} {} // Same here.
int someFunc();
private:
int a_ = 5;
int b_ = 7;
std::string s_{"Foo"};
Bar bar_{"Test"};
};
I would say use it when possible. An exception is when the situation described in this answer applies.

Why C++ allows returning a reference to private members [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
class test {
public:
test(int value = 0): x(value) {}
int& get(){
return x;
}
private:
int x;
};
this will allow client code to mutate the private members
this is legal in C++, but why ?
Is there any situation where you would actually need to break the class encapsulation ?
Make a member as private, means you can not access it directly. But nothing restricts you to access it indirectly via a public member. It depends on you design. You can even do this:
class test {
public:
test() : x(y) {}
int &x;
private:
int y;
};
In your class, assume you want count how many times a member is read/write. So, you can make it private then put a member function which returns a refernce to the variable:
class test {
public:
test(int value = 0): x(value), count(0) {}
int& get(){
count++;
return x;
}
private:
int x;
int count;
};
I hope this example shows how making a member as private and then putting an indirect access to it can be useful.
Ffirst of all let's consider implementing what you describe. It would be very onerous to properly do so. Your example is easy enough. But what if the reference flowed through a number of functions before it reached the function that exposed it? The compiler would have to do exceptionally complex static analysis, beyond the levels of static analysis that are reasonable to expect from compiler writers.
So even if the designers wanted to ban this, it would not have been tractable to do so. Would the designers have wanted to stop this? Very doubtful. Had they done so, how would the [] operator be implemented on a container or a string?
Is there any situation where you would actually need to
break the class encapsulation
As example of the [] operator on containers and strings shows, this feature is in fact used to support encapsulation.
Why? Because C++ mainly tries to let you do whatever you want and not get in your way; it doesn't try very hard to keep you safe. If you want a safe language, use something else. You have something like object-orientation if you want to, but if you want to break out of that, more power to you. With great power comes great responsibility.
It's worth nothing that you don't even need this to break encapsulation; you could simply reinterpret a pointer to "test" as an integer and access the private field this way.

How to organize a class's member functions? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I put 'sets' just after the constructors because it is related to the object setup. I split gets (put gets in inquires) and sets but not sure if this is good or not. What is best practice for organizing member functions?
How about that?
class Foo
{
// Friends go here if it has
friend ...;
friend ...;
// First public, then protected and private
public:
// enums
enum {...}
// type defines.
typedef ...;
...
// Destructor and constructors
~Foo();
Foo(...);
Foo(...);
...
// Sets.
void setA(...);
void setB(...);
void setC(...);
...
// Inquiries (including gets).
A a() const;
B b() const;
...
// Operators.
void operator()(...);
...
// Operations.
void doSomething();
...
protected:
private:
};
It's hard to judge, it's up to your personal preference or company coding standard. By looking at your code, a few things I may not agree:
your declarations are not ordered from pubilc,'protected` then private
friend declaration has same effort when you declare them in private area as well. so I normally put them in private section, so it gives less noise in public section.
Below is the declaration order I normally use:
Use the specified order of declarations within a class: public: before private:, methods before data members (variables), etc.
class definition should start with its public: section, followed by its protected: section and then its private: section. If any of these sections are empty, omit them.
Within each section, the declarations generally should be in the following order:
Typedefs and Enums
Constants (static const data members)
Constructors
Destructor
Methods, including static methods
Data Members (except static const data members)
Friend declarations should always be in the private section, and the disabled copy constructor and other operators `should be at the end of the private: section. It should be the last thing in the class.