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.
Related
I work at a manufacturing plant that uses a large C++ project to automate the manufacturing process.
I see a certain practice all over the place that just seems to make code unnecessarily long and I was wondering if there is a specific reason this practice is used.
See below for a simplified example that demonstrates this practice.
First file:
class A {
private:
int a;
public:
int get_a()
{ return a; }
void set_a(int arg)
{ a = arg; }
};
Second file:
class B {
private:
int b;
public:
int get_b()
{ return b; }
void set_b(int arg)
{ b = arg; }
};
Third file:
class C {
private:
A obj1;
B obj2;
public:
int get_a()
{ return obj1.get_a(); }
int get_b()
{ return obj2.get_b(); }
void set_a(int arg)
{ obj1.set_a(arg); }
void set_b(int arg)
{ obj2.set_b(arg); }
};
It seems to me like a slight change in design philosophy could have drastically reduced the amount of code in the third file. Something like this:
class C {
public:
A obj1;
B obj2;
};
Having obj1 and obj2 be public members in the C class does not seem to be unsafe, because the A and B classes each safely handle the getting and setting of their own member variables.
The only disadvantage I can think of to doing it this way is that any instances of the C class that calls a function would need to do something like obj.obj1.get_a() instead of just obj.get_a() but this seems like much less of an inconvenience than having private A and B object instances in the C class and then manually needing to "relay" all of their member functions.
I realize for this simple example, it is not much extra code, but for this large project that my company uses, it adds literally tens of thousands of lines of code.
Am I missing something?
There can be many reasons. One is the following:
Imagine you write a function that does something with the member a. You want the same code to accept an A as well as a C. Your function could look like this:
template <typename T>
void foo(T& t) {
std::cout << " a = " << t.get_a();
}
This would not work with your C because it has a different interface.
Encapsulation has its benefits, but I agree with you that encapsulation for the sake of encapsulation very often leads to much more code and often to nothing else than that.
In general, forcing calling code to write something like obj.obj1.get_a() is discouraged, because it reveals implementations details. If you ever change e.g the type of a then your C has no control whatsoever on that change. On the other hand if in the origninal code a changes from int to double then C can decide whether to keep the int interface and do some conversion (if applicable) or to change its interface.
It does add a little extra code, but the important thing is your interface. A class has a responsibility, and the members it holds are implementation details. If you expose internal objects and force users to "get the object, then make calls on it" you are coupling the caller to the implementation more than if you just provide an interface that does the job for the user. As an analogy, [borrowed from wikipedia] when one wants a dog to walk, one does not command the dog's legs to walk directly; instead one commands the dog which then commands its own legs.
Law of Demeter / Wikipedia
More formally, the Law of Demeter for functions requires that a method m of an object O may only invoke the methods of the following kinds of objects:
O itself
m's parameters
Any objects created/instantiated within m
O's direct component objects
A global variable, accessible by O, in the scope of m
In particular, an object should avoid invoking methods of a member object returned by another method. For many modern object oriented languages that use a dot as field identifier, the law can be stated simply as "use only one dot". That is, the code a.b.c.Method() breaks the law where a.b.Method() does not.
I have got the following data structure:
class Element {
std::string getType();
std::string getId();
virtual std::vector<Element*> getChildren();
}
class A : public Element {
void addA(const A *a);
void addB(const B *b);
void addC(const C *c);
std::vector<Element*> getChildren();
}
class B : public Element {
void addB(const B *b);
void addC(const C *c);
std::vector<Element*> getChildren();
}
class C : public Element {
int someActualValue;
}
/* The classes also have some kind of container to store the pointers and
* child elements. But let's keep the code short. */
The data structure is used to pruduce a acyclic directed graph. The C class acts as a "leaf" containing actual data for algebra-tasks. A and B hold other information, like names, types, rules, my favourite color and the weather forecast.
I want to program a feature, where a window pops up and you can navigate through an already existing structure. On the way i want to show the path the user took with some pretty flow chart, which is clickable to go back in the hierarchy. Based on the currently visited Graph-Node (which could be either A, B or C) some information has to be computed and displayed.
I thought i could just make a std::vector of type Element* and use the last item as the active element i work with. I thought that was a pretty nice approach, as it makes use of the inheritance that is already there and keeps the code i need quite small.
But i have a lot of situations like these:
Element* currentElement;
void addToCurrentElement(const C *c) {
if(A *a = dynamic_cast<A*>(currentElement)) {
//doSomething, if not, check if currentElement is actually a B
}
}
Or even worse:
vector<C*> filterForC's(A* parent) {
vector<Element*> eleVec = parent.getChildren();
vector<C*> retVec;
for(Element* e : eleVec) {
if (e.getType() == "class C") {
C *c = dynamic_cast<C*>(e);
retVec.append(c);
}
}
}
It definitely is object oriented. It definitely does use inheritance. But it feels like i just threw all the comfort OOP gives me over board and decided to use raw pointers and bitshifts again. Googling the subject, i found a lot of people saying casting up/down is bad design or bad practice. I totally believe that this is true, but I want to know why exactly. I can not change most of the code as it is part of a bigger project, but i want to know how to counter something like this situation when i design a program in the future.
My Questions:
Why is casting up/down considered bad design, besides the fact that it looks horrible?
Is a dynamic_cast slow?
Are there any rules of thumb how i can avoid a design like the one i explained above?
There are a lot of questions on dynamic_cast here on SO. I read only a few and also don't use that method often in my own code, so my answer reflects my opinion on this subject rather than my experience. Watch out.
(1.) Why is casting up/down considered bad design, besides the fact that it looks horrible?
(3.) Are there any rules of thumb how i can avoid a design like the one i explained above?
When reading the Stroustrup C++ FAQ, imo there is one central message: don't trust the people which say never use a certain tool. Rather, use the right tool for the task at hand.
Sometimes, however, two different tools can have a very similar purpose, and so is it here. You basically can recode any functionality using dynamic_cast through virtual functions.
So when is dynamic_cast the right tool? (see also What is the proper use case for dynamic_cast?)
One possible situation is when you have a base class which you can't extend, but nevertheless need to write overloaded-like code. With dynamic-casting you can do that non-invasive.
Another one is where you want to keep an interface, i.e. a pure virtual base class, and don't want to implement the corresponding virtual function in any derived class.
Often, however, you rather want to rely on virtual function -- if only for the reduced uglyness. Further it's more safe: a dynamic-cast can fail and terminate your program, a virtual function call (usually) won't.
Moreover, implemented in terms of pure functions, you will not forget to update it in all required places when you add a new derived class. On the other hand, a dynamic-cast can easily be forgotten in the code.
Virtual function version of your example
Here is the example again:
Element* currentElement;
void addToCurrentElement(const C *c) {
if(A *a = dynamic_cast<A*>(currentElement)) {
//doSomething, if not, check if currentElement is actually a B
}
}
To rewrite it, in your base add a (possibly pure) virtual functions add(A*), add(B*) and add(C*) which you overload in the derived classes.
struct A : public Element
{
virtual add(A* c) { /* do something for A */ }
virtual add(B* c) { /* do something for B */ }
virtual add(C* c) { /* do something for C */ }
};
//same for B, C, ...
and then call it in your function or possibly write a more concise function template
template<typename T>
void addToCurrentElement(T const* t)
{
currentElement->add(t);
}
I'd say this is the standard approach. As mentioned, the drawback could be that for pure virtual functions you require N*N overloads where maybe N might be enough (say, if only A::add requires a special treatment).
Other alternatives might use RTTI, the CRTP pattern, type erasure, and possibly more.
(2.) Is a dynamic_cast slow?
When considering what the majority of answers throughout the net state, then yes, a dynamic cast seems to be slow, see here for example.
Yet, I don't have practical experience to support or disconfirm this statement.
I have a question about implementing interface in C++:
Suppose there is an interface:
class A
{
virtual void f() = 0;
};
When implementing this, I wonder if there's a way to do something like:
class B : public A {
void f(int arg=0) {....} // unfortunately it does not implement f() this way
};
I want to keep the iterface clean. When client code calls through public interface A, arg is always set to 0 automatically. However when I call it through B, I have the flexibility to call it with arg set to some different value. Is it achievable?
EDIT: Since I control the interface and implementation, I am open to any suggestions, Macros, templates, functors, or anything else that makes sense. I just want to have a minimal and clean code base. The class is big, and I don't want to write any code that not absolutely necessary - e.g. another function that simply forwards to the actual implementation.
EDIT2: Just want to clarify a bit: The public interface is provided to client. It is more restrictive than Class B interface, which is only used internally. However the function f() is essentially doing the same thing, other than minor different treatment based on input arg. The real class has quite some interface functions, and the signature is complex. Doing function forwarding quickly results in tedious code repetition, and it pollutes the internal interface for B. I wonder what is the best way to deal with this in C++.
Thanks!
Yes, just make two separate functions:
class B : public A {
void f() { return f(0); }
void f(int arg) { .... }
};
When you have an interface, the basic principle should be that a function ALWAYS takes the same arguments and ALWAYS operates in the same way, no matter what the derived class is doing. Adding extra arguments is not allowed, because that presumes that the "thing" that operates on the object "knows" what the argument is/does.
There are several ways around this problem - thre that spring to mind immediately are:
Add the argument to the interface/baseclass.
Don't use an argument, but some extra function that [when the derived object is created or some other place that "knows the difference"] stores the extra information inside the object that needs it.
Add another class that "knows" what the argument is inside the class.
An example of the second one would be:
class B: public A
{
private:
int x;
public:
B() x(0) { ... } // default is 0.
void f() { ... uses x ... }
void setX(int newX) { x = newX; };
int getX() { return x; }
};
So, when you want to use x with another value than zero, you call bobject->setX(42); or something like that.
From your descriptions I'd say you should provide two classes, both with a specific responsibility: One to implement the desired functionality, the other to provide the needed interface to the client. That way you separate concerns and dont violate the SRP:
class BImpl {
public:
doF(int arg);
};
class B : public A {
BImpl impl;
public:
virtual void f() override {
impl.doF(0);
}
};
Doing function forwarding quickly results in tedious code repetition, and it pollutes the internal interface for B. I wonder what is the best way to deal with this in C++.
It sounds like you need to write a script to automate part of the process.
There's a feature called anonymous class in C++. It's similar with anonymous struct in C. I think this feature is invented because of some needs, but I can't figure out what that is.
Can I have some example which really needs anonymous class?
The feature is there because struct and class are the same thing - anything you can do with one, you can do with the other. It serves exactly the same purpose as an anonymous struct in C; when you want to group some stuff together and declare one or more instances of it, but don't need to refer to that type by name.
It's less commonly used in C++, partly because C++ designs tend to be more type-oriented, and partly because you can't declare constructors or destructors for anonymous classes.
It is not really needed in a strict sense and never was. I.e. you could always assign a name, for example anonymous1, anonymous2 etc. But keeping track of more names than necessary is always a hassle.
Where it is helpfull is at any place where one wants to group data without giving a name to that group. I could come up with a several examples:
class foo {
class {
public:
void validate( int x ) { m_x = x; }
bool valid() { return m_exists; }
private:
int m_x;
bool m_exists;
} maybe_x;
};
In this case the int and the bool logically belong together, so it makes sense to group them. However for this concrete example it probably makes sense to create an actual optional type or use one of the available ones, because this pattern is most likely used at other places as well. In other cases this pattern of grouping might be so special, that it deserves to stay in that class only.
I really do assume though, that anonymous classes are rarely used (I have only used them a couple of times in my live probably). Often when one want's to group data, this is not class or scope specific but also a grouping which also makes sense at other places.
Maybe it was sometimes helpful to make nested functions like:
void foo() {
class {
void operator()(){
}
} bar;
bar();
}
But now we have lambdas and anonymous classes are left only for compatibility reasons.
The use of anonymous classes is for preserving compatibility with existing C code.
Example:
In some C code, the use of typedef in conjunction with anonymous structures is prevalent.
There is an example of anonymous structs that can be used with Qt 5's Signal/Slot system with ANY class and without the QObject derivative requirement:
void WorkspaceWidget::wwShowEvent()
{
//Show event: query a reload of the saved state and geometry
gcmessage("wwShowEvent "+ this->title());
struct{void* t; void operator()(){ static_cast<WorkspaceWidget*>(t)->wwReloadWindowState(); }}f;
f.t=this;
QObject::connect( &reloadStateTimer, &QTimer::timeout, f);
reloadStateTimer.start();
}
void WorkspaceWidget::wwReloadWindowState()
{
gcmessage( dynamic_cast<QObject*>(this)->metaObject()->className());
}
Basically, I need to connect a timer signal to a non-QObject derived class, but want to pass mt "this" properly.
QObject::connect can be connected to ordinary function in Qt 5, so this anonymous class is actually a functor that keeps the this pointer in itself, still passing the slot connection.
Also you can do things with auto in anonymous (vs2015)
struct {
auto* operator->() {return this;}
//do other functions
} mystruct;
I have a simple, low-level container class that is used by a more high-level file class. Basically, the file class uses the container to store modifications locally before saving a final version to an actual file. Some of the methods, therefore, carry directly over from the container class to the file class. (For example, Resize().)
I've just been defining the methods in the file class to call their container class variants. For example:
void FileClass::Foo()
{
ContainerMember.Foo();
}
This is, however, growing to be a nuisance. Is there a better way to do this?
Here's a simplified example:
class MyContainer
{
// ...
public:
void Foo()
{
// This function directly handles the object's
// member variables.
}
}
class MyClass
{
MyContainer Member;
public:
void Foo()
{
Member.Foo();
// This seems to be pointless re-implementation, and it's
// inconvenient to keep MyContainer's methods and MyClass's
// wrappers for those methods synchronized.
}
}
Well, why not just inherit privatly from MyContainer and expose those functions that you want to just forward with a using declaration? That is called "Implementing MyClass in terms of MyContainer.
class MyContainer
{
public:
void Foo()
{
// This function directly handles the object's
// member variables.
}
void Bar(){
// ...
}
}
class MyClass : private MyContainer
{
public:
using MyContainer::Foo;
// would hide MyContainer::Bar
void Bar(){
// ...
MyContainer::Bar();
// ...
}
}
Now the "outside" will be able to directly call Foo, while Bar is only accessible inside of MyClass. If you now make a function with the same name, it hides the base function and you can wrap base functions like that. Of course, you now need to fully qualify the call to the base function, or you'll go into an endless recursion.
Additionally, if you want to allow (non-polymorphical) subclassing of MyClass, than this is one of the rare places, were protected inheritence is actually useful:
class MyClass : protected MyContainer{
// all stays the same, subclasses are also allowed to call the MyContainer functions
};
Non-polymorphical if your MyClass has no virtual destructor.
Yes, maintaining a proxy class like this is very annoying. Your IDE might have some tools to make it a little easier. Or you might be able to download an IDE add-on.
But it isn't usually very difficult unless you need to support dozens of functions and overrides and templates.
I usually write them like:
void Foo() { return Member.Foo(); }
int Bar(int x) { return Member.Bar(x); }
It's nice and symmetrical. C++ lets you return void values in void functions because that makes templates work better. But you can use the same thing to make other code prettier.
That's delegation inheritance and I don't know that C++ offers any mechanism to help with that.
Consider what makes sense in your case - composition (has a) or inheritance (is a) relationship between MyClass and MyContainer.
If you don't want to have code like this anymore, you are pretty much restricted to implementation inheritance (MyContainer as a base/abstract base class). However you have to make sure this actually makes sense in your application, and you are not inheriting purely for the implementation (inheritance for implementation is bad).
If in doubt, what you have is probably fine.
EDIT: I'm more used to thinking in Java/C# and overlooked the fact that C++ has the greater inheritance flexibility Xeo utilizes in his answer. That just feels like nice solution in this case.
This feature that you need to write large amounts of code is actually necessary feature. C++ is verbose language, and if you try to avoid writing code with c++, your design will never be very good.
But the real problem with this question is that the class has no behaviour. It's just a wrapper which does nothing. Every class needs to do something other than just pass data around.
The key thing is that every class has correct interface. This requirement makes it necessary to write forwarding functions. The main purpose of each member function is to distribute the work required to all data members. If you only have one data member, and you've not decided yet what the class is supposed to do, then all you have is forwarding functions. Once you add more member objects and decide what the class is supposed to do, then your forwarding functions will change to something more reasonable.
One thing which will help with this is to keep your classes small. If the interface is small, each proxy class will only have small interface and the interface will not change very often.