encapsulation difficulty in nested c++ classes - c++

We all are familiar with the concept of encapsulation and abstraction but sometimes this may lead to an obstacle I'm curious about the tricks or methods or whatever you call them to solve the problem.
here we have a nested c++ class:
#include <iostream>
using namespace std;
class Foo {
public:
int get_foo_var()
{
return foo_var;
}
void set_foo_var(int a)
{
foo_var = a;
}
private:
int foo_var;
};
class Bar {
public:
Foo get_foo()
{
return foo;
}
private:
Foo foo;
};
int main()
{
Bar bar;
bar.get_foo().set_foo_var(2);
cout << bar.get_foo().get_foo_var() << endl;
}
as you see here, get_foo() returns a copy of foo_var(it's value) which means it is not the reference to the original one and changing it does nothing, thus nothing is changed.
one solution might be changing to get_foo() in a way that returns a reference and not a value but this is of course in contrast with the concept of encapsulation.
what are the solutions to solve this problem without breaking software designing principles?
UPDATE
one pointed out setting foo_var by a function in bar class:
class Bar {
public:
void set_foo_var(int a) {
foo.set_foo_var(a);
}
private:
Foo foo;
};
but I think this violates encapsulation and abstraction! the whole concept of abstraction is if "foo" is related to "Foo" and "bar" is related to "Bar", that most of foo manipulations should be done in Foo class and some manipulations can be applied in other classes. what about the first situtation? (the situtation in which foo manipulation has nothing to do with Bar and so manipulating foo in bar is stupid!)

Whether you want to return a copy of or a reference to something is a high-level design decision. Both ways can be required, depending on the context.
In this particular example, you could add a corresponding method in Bar to modify the Foo behind it:
class Bar {
public:
void set_foo_var(int a) {
foo.set_foo_var(a);
}
private:
Foo foo;
};
Is this good or bad? The answer is: we cannot tell you. Generally, it's hard to seriously talk about good class design with names like "Foo" and "Bar". What's good and bad depends on the actual, real usage scenario! :)

Let's look at this from a purely conceptual level for a minute. This what your design says:
There exists one conceptual Foo entity for every Bar instance (because I can get a Foo from a Bar, and its state depends on which Bar I get it from).
Each Foo instance belongs to the Bar instance it came from (because operations on a Foo change the Bar it came from - the next time I ask for a Foo from a Bar, the previous Foo's changes are reflected).
A Foo has the same lifetime as its Bar (because I can ask for it at any time in the Bar's lifetime, I can use it as long as Bar exists, and the caller of get_foo() does not manage the lifetime of the returned Foo object).
Another way of looking at it is that Foo is already designed as part of Bar's internal state, a "conceptual member variable", regardless of whether it is actually implemented that way.
Given what your public interface is already telling you, how does returning a non-const reference to a private member really break encapsulation? Could you change the implementation so that Foo isn't a private member variable, yet still use the same public interface? Yes, you could. The only implementation changes that would force you to change the public interface ALSO force you to change the conceptual interface described above.
Implementation rules of thumb can be over-applied. Move past mechanics and look at conceptual design instead. Assuming you're OK with what your design is implying, in this case I say that returning a reference to a private member variable does NOT break encapsulation. At least that's my take on it.
An alternative is to have Foo and Bar less tightly coupled.
class Bar {
public:
Foo get_foo()
{
return foo;
}
set_foo(Foo new_foo)
{
// Update foo with new_foo's values
foo = new_foo;
}
private:
Foo foo;
};
In this case, Foo reflects some part of Bar's internal state at the time it was requested, but isn't tied to the Bar it came from. You have to explicitly call set_foo() to update Bar. Without that requirement, Foo really is conceptually a member variable regardless of how you implement it.

Related

C++ API: Modifing internal objects

I've got two related questions.
At the moment I am designing/writing a C++ API, in which I need to be able to modify an object that is held by another object.
It is comparable to this example:
class Bar
{
public:
Bar(int x) : num(x){}
void setNum(int x)
{
num = x;
}
int getNum()
{
return num;
}
private:
int num;
};
class Foo
{
public:
Foo() = default;
void setBar(std::unique_ptr<Bar> newBar)
{
bar = std::move(newBar);
}
Bar* getBar()
{
return bar.get();
}
private:
std::unique_ptr<Bar> bar;
};
The class Foo takes ownership of Bar, however, Bar must be able to be modified.
Here, Foo is the main class the user would interact with.
Whilst Bar could be considered more as a data type, which changes the output of Foo.
Is the solution of returning a raw pointer to Bar the preferred option?
I have the feeling, that this brakes the encapsulation which is a no-go for API design.
My googling efforts haven't given me a concrete answer to exactly this problem yet.
But I might just be looking with the wrong search terms.
The second part to this question is, how this example would change, if Bar would be stored in a container in Foo.
Would I return a pointer to the whole container, an iterator for the container ...?
If you worry about getBar breaking the encapsulation, then you should also see void setBar(std::unique_ptr<Bar> newBar) as such a breakage.
Because allowing to set bar from outside does make the knowledge about bar possibly none exclusive to Foo and the one passing Bar to Foo might have still the possibility to modify the bar so Foo can no do any assumptions about the state of Bar, as it could change anytime.
On the other hand, if you only want to have reading access to Bar trough Foo then a const Bar* getBar() or const Bar& getBar() would not break the encapsulation that much, because getBar would not allow changing Bar.
Is the solution of returning a raw pointer to Bar the preferred option?
It's a solution and not necessarily a bad one. Returning a reference would be preferable in cases where the object always exists (not in this case since Foo's default constructor doesn't create a Bar).
Some programmers prefer to use a wrapper for bare pointers (such as observer_ptr, which has been proposed to the standard) to distinguish it from a pointer whose purpose is to iterate an array, or from owning bare pointers (latter of which should be avoided).
I have the feeling, that this brakes the encapsulation
Your whole premise is to break the encapsulation since you want to "modify internal objects". If you want to avoid breakage of encapsulation, then you may need to change the design further up so that you don't need to modify internal objects (externally).
A solution that doesn't break encapsulation is to provide a specific interface to Foo for modification, such as:
void Foo::transmogrify_bar(int gadgets) {
bar->transmofgrify(gadgets);
}
Whether this encapsulation is useful for your API is another matter. In some cases it is essential, in others it doesn't matter much.
if Bar would be stored in a container in Foo. Would I return a pointer to the whole container, an iterator for the container ...?
Would you want the client to be able to modify the container (add, remove elements)?
This is breaking the encapsulation further. Instead, you could have begin and end iterators that don't allow modification of the container itself, which brings you to an equivalent encapsulation of the pointer return in the case of single object.
You could provide only const iterators, and add iterator as an argument to transmogrify to keep encapsulation of modifying Bar.
Finally, for full encapsulation, you would need to use PIMPL pattern to hide Bar completely.

C++ : Access a sub-object's methods inside an object

I am starting to code bigger objects, having other objects inside them.
Sometimes, I need to be able to call methods of a sub-object from outside the class of the object containing it, from the main() function for example.
So far I was using getters and setters as I learned.
This would give something like the following code:
class Object {
public:
bool Object::SetSubMode(int mode);
int Object::GetSubMode();
private:
SubObject subObject;
};
class SubObject {
public:
bool SubObject::SetMode(int mode);
int SubObject::GetMode();
private:
int m_mode(0);
};
bool Object::SetSubMode(int mode) { return subObject.SetMode(mode); }
int Object::GetSubMode() { return subObject.GetMode(); }
bool SubObject::SetMode(int mode) { m_mode = mode; return true; }
int SubObject::GetMode() { return m_mode; }
This feels very sub-optimal, forces me to write (ugly) code for every method that needs to be accessible from outside. I would like to be able to do something as simple as Object->SubObject->Method(param);
I thought of a simple solution: putting the sub-object as public in my object.
This way I should be able to simply access its methods from outside.
The problem is that when I learned object oriented programming, I was told that putting anything in public besides methods was blasphemy and I do not want to start taking bad coding habits.
Another solution I came across during my research before posting here is to add a public pointer to the sub-object perhaps?
How can I access a sub-object's methods in a neat way?
Is it allowed / a good practice to put an object inside a class as public to access its methods? How to do without that otherwise?
Thank you very much for your help on this.
The problem with both a pointer and public member object is you've just removed the information hiding. Your code is now more brittle because it all "knows" that you've implemented object Car with 4 object Wheel members. Instead of calling a Car function that hides the details like this:
Car->SetRPM(200); // hiding
You want to directly start spinning the Wheels like this:
Car.wheel_1.SetRPM(200); // not hiding! and brittle!
Car.wheel_2.SetRPM(200);
And what if you change the internals of the class? The above might now be broken and need to be changed to:
Car.wheel[0].SetRPM(200); // not hiding!
Car.wheel[1].SetRPM(200);
Also, for your Car you can say SetRPM() and the class figures out whether it is front wheel drive, rear wheel drive, or all wheel drive. If you talk to the wheel members directly that implementation detail is no longer hidden.
Sometimes you do need direct access to a class's members, but one goal in creating the class was to encapsulate and hide implementation details from the caller.
Note that you can have Set and Get operations that update more than one bit of member data in the class, but ideally those operations make sense for the Car itself and not specific member objects.
I was told that putting anything in public besides methods was blasphemy
Blanket statements like this are dangerous; There are pros and cons to each style that you must take into consideration, but an outright ban on public members is a bad idea IMO.
The main problem with having public members is that it exposes implementation details that might be better hidden. For example, let's say you are writing some library:
struct A {
struct B {
void foo() {...}
};
B b;
};
A a;
a.b.foo();
Now a few years down you decide that you want to change the behavior of A depending on the context; maybe you want to make it run differently in a test environment, maybe you want to load from a different data source, etc.. Heck, maybe you just decide the name of the member b is not descriptive enough. But because b is public, you can't change the behavior of A without breaking client code.
struct A {
struct B {
void foo() {...}
};
struct C {
void foo() {...}
};
B b;
C c;
};
A a;
a.c.foo(); // Uh oh, everywhere that uses b needs to change!
Now if you were to let A wrap the implementation:
class A {
public:
foo() {
if (TESTING) {
b.foo();
} else {
c.foo();
}
private:
struct B {
void foo() {...}
};
struct C {
void foo() {...}
};
B b;
C c;
};
A a;
a.foo(); // I don't care how foo is implemented, it just works
(This is not a perfect example, but you get the idea.)
Of course, the disadvantage here is that it requires a lot of extra boilerplate, like you have already noticed. So basically, the question is "do you expect the implementation details to change in the future, and if so, will it cost more to add boilerplate now, or to refactor every call later?" And if you are writing a library used by external users, then "refactor every call" turns into "break all client code and force them to refactor", which will make a lot of people very upset.
Of course instead of writing forwarding functions for each function in SubObject, you could just add a getter for subObject:
const SubObject& getSubObject() { return subObject; }
// ...
object.getSubObject().setMode(0);
Which suffers from some of the same problems as above, although it is a bit easier to work around because the SubObject interface is not necessarily tied to the implementation.
All that said, I think there are certainly times where public members are the correct choice. For example, simple structs whose primary purpose is to act as the input for another function, or who just get a bundle of data from point A to point B. Sometimes all that boilerplate is really overkill.

Passing arbitrary information for a functional parameter to use

In C++:
I have an object I'll call Foo.
Foo performs statistical operations on a supplied data set. The first step of the process involves a fitting function, and a functional parameter can be supplied so that the user can specify the type of model being used.
The problem is that I now have a situation where the function parameter needs to have access to data that does not exist in Foo but rather in the object that is using Foo, which I will call Bar.
So Bar calls Foo to have Foo operate on Bar's data. Bar has a specific function it wants to use as the functional parameter but this function requires information specific to Bar.
I don't want to pass Bar because if I code Foo up to receive Bar, then every time I have a new object that needs additional info passed to Foo, I will have to adjust the Foo class to accept that object.
I don't want to modify the functional parameter input in Foo because then I'll have to modify the functional parameter input for every new usage case as well.
I considered using a base class I'll call StandardFunc. Then, via virtual methods, Bar could create an object called ModifiedFunc that derives from StandardFunc. It could override the StandardFunc's function and also supply the additional info as class parameters. This doesn't work either because to avoid slicing I have to type-cast ModifiedFunc to StandardFunc. This means that inside Foo I have to change the type-cast line for every new object name.
Can someone please point me in the right direction for how I can allow users to pass either a functional parameter alongside arbitrary parameters the function requires without having to recode the Foo class for every different usage case? I'm really stuck on this.
EDIT: pseudo code example:
class Foo
{
void processHandler(function)
void process();
void process(function);
void theUsualFunction(vector); //the default function used by process
vector vec;
};
void Foo::process()
{
processHandler(theUsualFunction);
}
void Foo::process(function f)
{
processHandler(f)
}
void Foo::processHandler(function f)
{
f(vec)
//do other stuff to vec
}
void Foo::theUsualFunction(vector v)
{
//default vec processor
}
class Bar
{
int x;
int y;
vector vec;
void theModifiedFunction(vector);
void callFooToProcess();
};
void Bar::theModifiedFunction(vector v)
{
//process v, but in a way that requires x and y
}
void Bar::callFooToProcess()
{
Foo foo;
foo.setVector(vec);
process(theModifiedFunction);
}
So this code is kind of an example of what I want to achieve, but it doesn't work as written. The reason is because I have no way of getting Bar::x and Bar::y to the function Foo::processHandler(function) without modifying the arguments for Foo::processHandler, and I don't want to do that because then every new class like Bar and every new theModifiedFunction that requires different data will require me to rewrite the arguments for processHandler.
This doesn't work either because to avoid slicing I have to type-cast ModifiedFunc to StandardFunc.
Slicing only occurs if you pass the argument by value. You should pass it as a pointer, that's how polymorphism is supposed to work.
Also, you can keep passing the argument by value if you make your class a template:
template<class Func>
class Foo {
void doStuff(Func func) {
...
}
}
Keep in mind though, that in this case Func has to be known at compile-time.
Although there may be other ways of handling this situation, I would suggest considering to have Bar contain Foo. This is called a has-a relationship [wiki]. The advantage of this is that you can use Foo as-is without modifying anything within Foo, as well as Bar need not pass around its private data. Hope the following code snippet would help you to understand the concept.
public class Bar
{
private Foo myFoo;
private int myInfo;
void a()
{
myFoo.doStuff(myInfo);
}
}

Enforce constness for pointed data in C++?

Let there be a Foo class with some const and non-const methods
struct Foo
{
Foo ();
~Foo();
void noSideEffect() const;
void withSideEffect();
};
I also have a Bar class, that need to refer to Foo in some way. To be more precise, maybe too precise for this question, Bar implements operators || and && for union and intersections, so two Bar instances need to kwow they are working on the same instance of Foo.
The simplest solution I found was to use a pointer to a Foo object:
struct Bar
{
Foo * p_foo;
Bar (Foo& foo)
: p_foo(&foo) {};
}
Now two bar instances can play together and see if they are both handling the same Foo. I'm almost happy.
But now I would like to sometimes use Bar with const Foo instances. Well, it might be easy, I just have to create a const Bar instance, right? There we go:
const Bar createBarFromConstFoo(const Foo& foo)
{
Foo* newfoo = const_cast<Foo*>(&foo);
const Bar newbar (*newfoo);
return newbar;
}
And now the nightmare begins (see Why doesn't C++ enforce const on pointer data?). I think I understand the why (the standard says so), my main problem is how to best cope with it.
Except this little standard thing, the createBarFomConstFoo does almost what I want since it is returning a const Bar.
Is there a way to prevent a const Bar to do nasty things with my (initially) const Foo (ie only call const methods of Foo) while allowing a non-const Bar to do everything?
Maybe there is no way to do that and it's an object design issue, but I do not see a simple alternative.
Edit: to downvoters, can you please explain why, I may be able to progress from your remarks...
Edit 2: Maybe obfuscating the real classes behing Foo and Bar was a bad idea, I just wanted to simplify things.
So Foo is in fact a Molecule (and in fact a Protein), which contains Atoms (many for a protein). Being able to select some atoms is the reason to create Bar, which is a SelectionOfAtoms.
It is sometimes convenient to select, from example, all hydrogens and oxygen atoms, so Bar implements unions and intersections. I want to be able to extract those atoms so SelectionOfAtoms implements a createNewMolecule() methods from the selected atoms. It therefore need a way to refer to the original molecule (maybe some kind of copy would do here but maybe not with the other requirements below).
But I recently felt the need to modify atoms of a selection, while keeping other atoms unmodified. Doing it through SelectionOfAtoms (Bar) was conveninent: it already knows where to find the Atoms (using the pointer) and the index of these atoms (internal implementation detail), so everything needed to change atoms is almost already here, except that I can either use Selection only on Molecule (non-const) or work on const Molecule and forget about modifying them or go into the const_cast horror.
I'm sure it's a pretty bad design, but it is what is already there, it can surely be improved a lot.
Using the STL as a guide, consider your molecule as a container, and your selection as something like an iterator or iterator range.
Now, in this scheme you'd have separate types for the const and non-const selections/iterators, which makes sense since they have different semantics. Making the constness a template parameter is probably a false economy unless there's a lot more code in the selection than you've suggested.
Now, you start off with either a const or a non-const molecule, and you know statically that you're getting ether a const_selection or (non-const) selection.
It Bar is not overly complex, you can make it a class template.
template <typename FooType>
struct Bar
{
FooType * p_foo;
Bar (FooType& foo)
: p_foo(&foo) {};
}
template <typename FooType>
Bar<FooType> makeBar(FooType& foo)
{
return Bar<FooType>(foo);
}

Writing a source function in c++11 properly

My head hurts: I've read so many blogs about C++11x's move semantics that my brain's gone mushy, so please can someone give me a short-but-sweet guide on how to make the following code work efficiently? Given a class Foo, I want to be able to write functions that return Foo objects in different states (sometimes called source functions), and to do this as efficiently as possible.
class Foo {
// Some methods and members
};
Foo getFirstFoo() {
Foo foo;
// Do some things to foo
return foo;
}
Foo getSecondFoo() {
Foo foo;
// Do some different things to foo
return foo;
}
int main() {
Foo f = getFoo();
// use f ...
f = getSecondFoo();
// use f ...
return 0;
}
I don't want to modify Foo much, and the idea is to allow all sorts of Foo objects to be created through a variety of non-member source functions, so adding ever more constructors would be missing the point.
In C++03 my options would be to wrap the returned object in an auto_ptr (a big downside being that the recipient code needs to know to handle a smart pointer), or to cross my fingers and hope that some sort of optimization might take place (likely for the first line in main, less so for the second). C++11x seems to provide something better through move semantics, but how would I take advantage of these? So I need to change the way objects are returns in the source functions, or add some move constructor to Foo, or both?
This is already optimal1, provided that move constructors are generated2:
class Foo {
public:
Foo(Foo&&) = default;
Foo& operator=(Foo&&) = default;
};
Returned values are rvalue references by default.
1 Well.... provided that your class Foo benefits from move construction at all. Remember, move is an optimization of copy. Some copies cannot be improved! E.g, unsuited:
struct Foo { int data; };
struct Foo2 { int data[5<<10]; };
well suited:
struct Foo3 { std::vector<std::string> data; };
See Move semantics - what it's all about? for a more general background on things like this.
2 Not all compilers do support that yet (even if they do implement rvalue references), so you might have to write the
move constructor
move assignment