c++: why not use friend for compositions? - c++

I'm a computational physicist trying to learn how to code properly. I've written several program by now, but the following canonical example keeps coming back, and I'm unsure as to how to handle it. Let's say that I have a composition of two objects such as
class node
{
int position;
};
class lattice
{
vector <node*> nodes;
double distance (node*,node*);
};
Now, this will not work, because position is a private member of node. I know of two ways to solve this: either you create an accessor such as getpos(){return position}, or make lattice a friend of node.
The second of these solutions seems a lot easier to me. However, I am under the impression that it is considered slightly bad practice, and that one generally ought to stick to accessors and avoid friend. My question is this: When should I use accessors, and when should I use friendship for compositions such as these?
Also, a bonus question that has been bugging me for some time: Why are compositions preferred to subclasses in the first place? To my understanding the HAS-A mnemonic argues this, but, it seems more intuitive to me to imagine a lattice as an object that has an object called node. That would then be an object inside of an object, e.i. a subclass?

Friend is better suited if you give access rights to only specific classes, rather than to all. If you define getpos(){return position}, position information will be publicly accessible via that getter method. If you use friend keyword, on the other hand, only the lattice class will be able to access position info. Therefore, it is purely dependent on your design decisions, whether you wanna make the information publicly accessible or not.

You made a "quasi class", this a textbook example of how not to do OOP because changing position doesn't change anything else in node. Even if changing position would change something in node, I would rethink the structure to avoid complexity and improve the compiler's ability to optimize your code.
I’ve witnessed C++ and Java programmers routinely churning out such
classes according to a sort of mental template. When I ask them to
explain their design, they often insist that this is some sort of
“canonical form” that all elementary and composite item (i.e.
non-container) classes are supposed to take, but they’re at a loss to
explain what it accomplishes. They sometimes claim that we need the
get and set functions because the member data are private, and, of
course, the member data have to be private so that they can be changed
without affecting other programs!
Should read:
struct node
{
int position;
};

Not all classes have to have private data members at all. If your intention is to create a new data type, then it may be perfectly reasonable for position to just be a public member. For instance, if you were creating a type of "3D Vectors", that is essentially nothing but a 3-tuple of numeric data types. It doesn't benefit from hiding its data members since its constructor and accessor methods have no fewer degrees of freedom than its internal state does, and there is no internal state that can be considered invalid.
template<class T>
struct Vector3 {
T x;
T y;
T z;
};
Writing that would be perfectly acceptable - plus overloads for various operators and other functions for normalizing, taking the magnitude, and so on.
If a node has no illegal position value, but no two nodes in a lattice cannot have the same position or some other constraint, then it might make sense for node to have public member position, while lattice has private member nodes.
Generally, when you are constructing "algebraic data types" like the Vector3<T> example, you use struct (or class with public) when you are creating product types, i.e. logical ANDs between other existent types, and you use std::variant when you are creating sum types, i.e. logical ORs between existent types. (And for completeness' sake, function types then take the place of logical implications.)
Compositions are preferred over inheritance when, like you say, the relationship is a "has-a" relationship. Inheritance is best used when you are trying to extend or link with some legacy code, I believe. It was previously also used as a poor approximation of sum types, before std::variant existed, because the union keyword really doesn't work very well. However, you are almost always better off using composition.

Concerning your example code, I am not sure that this poses a composition. In a composition, the child object does not exist as an independent entity. As a rule of thumb, it's life time is coupled with the container. Since you are using a vector<node*> nodes, I assume that the nodes are created somewhere else and lattice only has a pointer to these objects. An example for a composition would be
class lattice {
node n1; // a single object
std::vector<node> manyNodes;
};
Now, addressing the questions:
"When should I use accessors, and when should I use friendship for compositions such as these?"
If you use plenty of accessors in your code, your are creating structs and not classes in an OO sense. In general, I would argue that besides certain prominent exceptions such as container classes one rarely needs setters at all. The same can be argued for simple getters for plain members, except when the returning the property is a real part of the class interface, e.g. the number of elements in a container. Your interface should provide meaningful services that manipulate the internal data of your object. If you frequently get some internal data with a getter, then compute something and set it with an accessor you should put this computation in a method.
One of the main reasons why to avoid ´friend´ is because it introduces a very strong coupling between two components. The guideline here is "low coupling, high cohesion". Strong coupling is considered a problem because it makes code hard to change, and most time on software projects is spent in maintenance or evoluation. Friend is especially problematic because it allows unrelated code to be based on internal properties of your class, which can break encapsulation. There are valid use-cases for ´friend´ when the classes form a strongly related cluster (aka high cohesion).
"Why are compositions preferred to subclasses in the first place?"
In general, you should prefer plain composition over inheritance and friend classes since it reduces coupling. In a composition, the container class can only access the public interface of the contained class and has no knowledge about the internal data.
From a pure OOP point of view, your design has some weaknesses and is probably not very OO. One of the basic principles of OOP is encapsulation which means to couple related data and behavior into objects. The node class e.g. does not have any meaning other than storing a position, so it does not have any behavior. It seems that you modeled the data of your code but not the behavior. This can be a very appropriate design and lead to good code, but it not really object-oriented.
"To my understanding the HAS-A mnemonic argues this, but, it seems more intuitive to me to imagine a lattice as an object that has an object called node. That would then be an object inside of an object, e.i. a subclass?"
I think you got this wrong. Public inheritance models an is-a-relationship.
class A: public B {};
It basically says that objects of class A are a special kind of B, fulfilling all the assumptions that you can make about objects of type B. This is known as the Liskov substitution principle. It basically says that everywhere in your code where you use a B you should be able to also use an A. Considering this, class lattice: public node would mean that every lattice is a node. On the other hand,
class lattice {
int x;
node n;
int y;
};
means that an object of type lattice contains another object of type node, in C++ physically placed together with x and y. This is a has-a-relationship.

Related

Significance of classes over data-structures

Whats the significance of classes over data-structures or data-structures over classes?
Ok so The most basic ones can be that we can use "Access Specifiers In Classes" meaning we can prevent some and allow some to access our data.
next can be that data-hiding.
But whats the main thing that separates classes and data-structures? I mean why need data-structures when we have classes or vice-versa?
C++ has fundamantal types, and classes.
Struct and Class are both keywords that introduce a new class. There are slightly different defaults.
Data structures are an arrangement of data with some kind of invarient. They can be a class, they can contain classes, or they could be completely class free.
They are different categories of thing. It is like asking what the difference is between steel and an automobile.
In a course assignment, what the teacher is asking for is for you to know the definition the teacher or the text taught those terms meant. Terms mean what the context they are in tells them to mean. It is a matter of "are you paying attention" not "do you know this fact"; having asked it of the internet, you have already failed.
In terms of syntax, in C++ the only difference between a class and a struct is that members of a struct are public by default, while the members of a class are private by default.
From a perspective of implied design intent, however, there is a larger difference. struct was/is a feature of C, and was/is used (in both C and C++) to help the programmer organize Plain Old Data in useful ways. (for example, if you know every Person in your persons-database needs to store the person's first name, last name, and age, then you can put two char arrays and and int together in a struct Person and thereby make it more convenient to track all of that data as a unit, than if you had to store each of those fields separately).
C++ continues to provide that C-style struct functionality, but then goes further by adding additional features to better support object-oriented-programming. In particular, C++ adds explicit support for encapsulation (via the private and protected keywords), functionality-extension via inheritance, the explicit tying-together of code and data via methods, and run-time polymorphism via virtual methods. Note that all of these features can be approximated in C by manually following certain coding conventions, but by explicitly supporting them as part of the language, C++ makes them easier to use correctly and consistently.
Having done that, C++ then goes on to muddy the waters a bit, by making all of that new functionality available to structs as well as classes. (This is why the technical difference is so minor, as described in the first paragraph) However, I believe it is the case that when most programmers see a struct defined, they tend to have an implicit expectation that the struct is intended be used as a simple C-style data-storage/data-organization receptacle, whereas when they see a class, they expect it to include not just "some raw data" but also some associated business-logic, as implemented in the class's methods, and that the class will enforce its particular rules/invariants by requiring the calling code to call those methods, rather than allowing the calling code to read/write the class's member-variables directly. (That's why public member-variables are discouraged in a class, but less so in a struct -- because a public member-variable in a class-object contradicts this expectation, and violates the principle of least surprise).

How should I share data structures

Bjarne Stroustrup: My rule of thumb is that you should have a real
class with an interface and a hidden representation if and only if you
can consider an invariant for the class.
On a current project, I had a base class called Widget. It had private variables for x, y, width, height (basically a rect data structure) and public getters and setters for each. Their was no purpose to the class except being a dumb variable holder. In light of Bjarnes' comment above, I got rid of this class, but I'm wondering how I should share this data structure with child classes that need them. Should I just individually include them as members for each class? Put them inside a Widget namespace?
You can use a struct
e.g.
struct widget
{
int x;
int y;
int w;
int h;
};
I'm not sure I entirely agree with Bjarne (aside from invariants the ability to change the representation may be an important concern although in that case it may be important to even move the actual definition into a PImpl rather than just making it private). However, you can group variables into a structure with public access to its members if there is no concern about changed members and or invariants. In case, the members are indeed just lumped together without a semantic meaning, you might even just use a std::tuple:
typedef std::tuple<int, int, double, double> widget;
... although in this case the different members do have access functions - for technical reasons independent from invariants and forward compatibility.
I think you massively misread Stroustrup there, let me emphasise the part that I think is important:
My rule of thumb is that you should have a real class with an interface and a hidden representation if and only if you can consider an invariant for the class.
I believe he is specifically not talking about not using the keyword class in this situation but is referring to a logical class (or "real class"). The difference is quite significant. A class (note the lack of markdown) is a data structure with a self contained interface and possibly a hidden implementation (see pimpl idiom). That means, the workings of a (logical) class are invisible to the user and a class object is communicated with via member functions and free functions. In terms of data abstraction that is sometimes interpreted as "don't access member variables from the outside" but that's just a shallower wording of the core idea.
You should still use structured design for heterogeneous collections of data just as you do (or as Commander or Dietmar Kühl suggests). Whether or not you use the class or the struct keyword is personal taste, but I tend to use the struct keyword so it is clear that this type is not a class in the logical sense but just some data that belongs together. I find using a proper struct is preferable to an std::tuple as you can name all the members, giving them meaning, rather than accessing them by index and having to remember what every index was supposed to mean. In addition it is easier to modify and extend a struct in the future.

What, if anything, is wrong with a child class containing a parent class object in C++?

In C++ specifically, but also generally as an OO design principle, is there anything wrong with doing the following? Is it done in practice? If it shows a clear design flaw, what is a good alternative? Are there any advantages?
class Property {};
class CompositeProperty : public Property
{
...
private:
std::vector<Property> m_properties;
};
So specifically, can a derived class contain base class objects?
As I bit of background I have seen this used to model/mirror an XML structure but felt the design somewhat went in the face of is-a-is-inheritance and has-a-is-composition relationships for which one usually strives.
There is no flaw in design - in fact, this design is only one step away from the well-known and very useful composite pattern. However, there is a significant flaw in the implementation.
Your CompositeProperty aggregates instances of Property, rather than aggregating pointers. This kills the ability to use elements of the CompositeProperty polymorphically. You need to replace a vector of instances with a vector of pointers (preferably, smart pointers) in order to address this issue.
A classic place for the composite pattern is representation of expression trees: you start off with an abstract base, and then add representations for constants, variables, function calls, unary expressions, binary expressions, conditionals, and so on. Expressions such as constants and variables do not reference other expressions, while expressions such as unary expressions, binary expressions, and function calls do. This makes the object graph recursive, letting you represent expressions of arbitrary complexity.
So specifically, can a child class contain parent class objects?
In short YES
Please take a look at the Composite pattern.
Composite can be used when clients should ignore the difference between compositions of objects and individual objects. If programmers find that they are using multiple objects in the same way, and often have nearly identical code to handle each of them, then composite is a good choice; it is less complex in this situation to treat primitives and composites as homogeneous.
Nothing wrong with it at all but you may want to consider using pointers to the base/parent class. This allows for polymorphic behaviour of your objects. If you add instances of derived classes to your vector as it stands, you will suffer from object slicing.
There is nothing wrong with it.
Take this example (it's C#, but should be straightforward enough) where you define two sub-classes each containing an instance of the inherited one:
public class Person
{
public string Name;
}
public class MalePerson : Person
{
public Person BestFriend;
}
public class FemalePerson : Person
{
public Person BestFriend;
}
In my experience, including an instance of the superclass in the subclasses is most commonly used to either model a hierarchy between heterogeneous objects or refer to an object with as few assumptions as possible.

C++ should all member variable use accessors and mutator

I have about 15~20 member variables which needs to be accessed, I was wondering
if it would be good just to let them be public instead of giving every one of them
get/set functions.
The code would be something like
class A { // a singleton class
public:
static A* get();
B x, y, z;
// ... a lot of other object that should only have one copy
// and doesn't change often
private:
A();
virtual ~A();
static A* a;
};
I have also thought about putting the variables into an array, but I don't
know the best way to do a lookup table, would it be better to put them in an array?
EDIT:
Is there a better way than Singleton class to put them in a collection
The C++ world isn't quite as hung up on "everything must be hidden behind accessors/mutators/whatever-they-decide-to-call-them-todays" as some OO-supporting languages.
With that said, it's a bit hard to say what the best approach is, given your limited description.
If your class is simply a 'bag of data' for some other process, than using a struct instead of a class (the only difference is that all members default to public) can be appropriate.
If the class actually does something, however, you might find it more appropriate to group your get/set routines together by function/aspect or interface.
As I mentioned, it's a bit hard to tell without more information.
EDIT: Singleton classes are not smelly code in and of themselves, but you do need to be a bit careful with them. If a singleton is taking care of preference data or something similar, it only makes sense to make individual accessors for each data element.
If, on the other hand, you're storing generic input data in a singleton, it might be time to rethink the design.
You could place them in a POD structure and provide access to an object of that type :
struct VariablesHolder
{
int a;
float b;
char c[20];
};
class A
{
public:
A() : vh()
{
}
VariablesHolder& Access()
{
return vh;
}
const VariablesHolder& Get() const
{
return vh;
}
private:
VariablesHolder vh;
};
No that wouldn't be good. Image you want to change the way they are accessed in the future. For example remove one member variable and let the get/set functions compute its value.
It really depends on why you want to give access to them, how likely they are to change, how much code uses them, how problematic having to rewrite or recompile that code is, how fast access needs to be, whether you need/want virtual access, what's more convenient and intuitive in the using code etc.. Wanting to give access to so many things may be a sign of poor design, or it may be 100% appropriate. Using get/set functions has much more potential benefit for volatile (unstable / possibly subject to frequent tweaks) low-level code that could be used by a large number of client apps.
Given your edit, an array makes sense if your client is likely to want to access the values in a loop, or a numeric index is inherently meaningful. For example, if they're chronologically ordered data samples, an index sounds good. Summarily, arrays make it easier to provide algorithms to work with any or all of the indices - you have to consider whether that's useful to your clients; if not, try to avoid it as it may make it easier to mistakenly access the wrong values, particularly if say two people branch some code, add an extra value at the end, then try to merge their changes. Sometimes it makes sense to provide arrays and named access, or an enum with meaningful names for indices.
This is a horrible design choice, as it allows any component to modify any of these variables. Furthermore, since access to these variables is done directly, you have no way to impose any invariant on the values, and if suddenly you decide to multithread your program, you won't have a single set of functions that need to be mutex-protected, but rather you will have to go off and find every single use of every single data member and individually lock those usages. In general, one should:
Not use singletons or global variables; they introduce subtle, implicit dependencies between components that allow seemingly independent components to interfere with each other.
Make variables const wherever possible and provide setters only where absolutely required.
Never make variables public (unless you are creating a POD struct, and even then, it is best to create POD structs only as an internal implementation detail and not expose them in the API).
Also, you mentioned that you need to use an array. You can use vector<B> or vector<B*> to create a dynamically-sized array of objects of type B or type B*. Rather than using A::getA() to access your singleton instance; it would be better to have functions that need type A to take a parameter of type const A&. This will make the dependency explicit, and it will also limit which functions can modify the members of that class (pass A* or A& to functions that need to mutate it).
As a convention, if you want a data structure to hold several public fields (plain old data), I would suggest using a struct (and use in tandem with other classes -- builder, flyweight, memento, and other design patterns).
Classes generally mean that you're defining an encapsulated data type, so the OOP rule is to hide data members.
In terms of efficiency, modern compilers optimize away calls to accessors/mutators, so the impact on performance would be non-existent.
In terms of extensibility, methods are definitely a win because derived classes would be able to override these (if virtual). Another benefit is that logic to check/observe/notify data can be added if data is accessed via member functions.
Public members in a base class is generally a difficult to keep track of.

Best practices for a class with many members

Any opinions on best way to organize members of a class (esp. when there are many) in C++. In particular, a class has lots of user parameters, e.g. a class that optimizes some function and has number of parameters such as # of iterations, size of optimization step, specific method to use, optimization function weights etc etc. I've tried several general approaches and seem to always find something non-ideal with it. Just curious others experiences.
struct within the class
struct outside the class
public member variables
private member variables with Set() & Get() functions
To be more concrete, the code I'm working on tracks objects in a sequence of images. So one important aspect is that it needs to preserve state between frames (why I didn't just make a bunch of functions). Significant member functions include initTrack(), trackFromLastFrame(), isTrackValid(). And there are a bunch of user parameters (e.g. how many points to track per object tracked, how much a point can move between frames, tracking method used etc etc)
If your class is BIG, then your class is BAD.
A class should respect the Single Responsibility Principle , i.e. : A class should do only one thing, but should do it well. (Well "only one" thing is extreme, but it should have only one role, and it has to be implemented clearly).
Then you create classes that you enrich by composition with those single-role little classes, each one having a clear and simple role.
BIG functions and BIG classes are nest for bugs, and misunderstanding, and unwanted side effects, (especially during maintainance), because NO MAN can learn in minutes 700 lines of code.
So the policy for BIG classes is: Refactor, Composition with little classes targetting only at what they have do.
if i had to choose one of the four solutions you listed: private class within a class.
in reality: you probably have duplicate code which should be reused, and your class should be reorganized into smaller, more logical and reusable pieces. as GMan said: refactor your code
First, I'd partition the members into two sets: (1) those that are internal-only use, (2) those that the user will tweak to control the behavior of the class. The first set should just be private member variables.
If the second set is large (or growing and changing because you're still doing active development), then you might put them into a class or struct of their own. Your main class would then have a two methods, GetTrackingParameters and SetTrackingParameters. The constructor would establish the defaults. The user could then call GetTrackingParameters, make changes, and then call SetTrackingParameters. Now, as you add or remove parameters, your interface remains constant.
If the parameters are simple and orthogonal, then they could be wrapped in a struct with well-named public members. If there are constraints that must be enforced, especially combinations, then I'd implement the parameters as a class with getters and setters for each parameter.
ObjectTracker tracker; // invokes constructor which gets default params
TrackerParams params = tracker.GetTrackingParameters();
params.number_of_objects_to_track = 3;
params.other_tracking_option = kHighestPrecision;
tracker.SetTrackingParameters(params);
// Now start tracking.
If you later invent a new parameter, you just need to declare a new member in the TrackerParams and initialize it in ObjectTracker's constructor.
It all depends:
An internal struct would only be useful if you need to organize VERY many items. And if this is the case, you ought to reconsider your design.
An external struct would be useful if it will be shared with other instances of the same or different classes. (A model, or data object class/struct might be a good example)
Is only ever advisable for trivial, throw-away code.
This is the standard way of doing things but it all depends on how you'll be using the class.
Sounds like this could be a job for a template, the way you described the usage.
template class FunctionOptimizer <typename FUNCTION, typename METHOD,
typename PARAMS>
for example, where PARAMS encapsulates simple optimization run parameters (# of iterations etc) and METHOD contains the actual optimization code. FUNCTION describes the base function you are targeting for optimization.
The main point is not that this is the 'best' way to do it, but that if your class is very large there are likely smaller abstractions within it that lend themselves naturally to refactoring into a less monolithic structure.
However you handle this, you don't have to refactor all at once - do it piecewise, starting small, and make sure the code works at every step. You'll be surprised how much better you quickly feel about the code.
I don't see any benefit whatsoever to making a separate structure to hold the parameters. The class is already a struct - if it were appropriate to pass parameters by a struct, it would also be appropriate to make the class members public.
There's a tradeoff between public members and Set/Get functions. Public members are a lot less boilerplate, but they expose the internal workings of the class. If this is going to be called from code that you won't be able to refactor if you refactor the class, you'll almost certainly want to use Get and Set.
Assuming that the configuration options apply only to this class, use private variables that are manipulated by public functions with meaningful function names. SetMaxInteriorAngle() is much better than SetMIA() or SetParameter6(). Having getters and setters allows you to enforce consistency rules on the configuration, and can be used to compensate for certain amounts of change in the configuration interface.
If these are general settings, used by more than one class, then an external class would be best, with private members and appropriate functions.
Public data members are usually a bad idea, since they expose the class's implementation and make it impossible to have any guaranteed relation between them. Walling them off in a separate internal struct doesn't seem useful, although I would group them in the list of data members and set them off with comments.