How to implement class composition in C++? - c++

If I understand correctly we have at least two different ways of implementing composition. (The case of implementation with smart pointers is excluded for simplicity. I almost don't use STL and have no desire to learn it.)
Let's have a look at Wikipedia example:
class Car
{
private:
Carburetor* itsCarb;
public:
Car() {itsCarb=new Carburetor();}
virtual ~Car() {delete itsCarb;}
};
So, it's one way - we have a pointer to object as private member.
One can rewrite it to look like this:
class Car
{
private:
Carburetor itsCarb;
};
In that case we have an object itself as private member. (By the way, am I right to call this entity an object from the terminology point of view?)
In the second case it is not obligatory to implicitly call default constructor (if one need to call non-default constructor it's possible to do it in initializer list) and destructor. But it's not a big problem...
And of course in some aspects these two cases differ more appreciably. For example it's forbidden to call non-const methods of Carburetor instance from const methods of Car class in the second case...
Are there any "rules" to decide which one to use? Am I missing something?

In that case we have an object itself as private member. (By the way, calling this entity as object am I write from the terminology point of view?)
Yes you can say "an object" or "an instance" of the class.
You can also talk about including the data member "by value" instead of "by pointer" (because "by pointer" and "by value" is the normal way to talk about passing parameters, therefore I expect people would understand those terms being applied to data members).
Is there any "rules" to decide which one to use? Am I missed something?
If the instance is shared by more than one container, then each container should include it by pointer instead of value; for example if an Employee has a Boss instance, include the Boss by pointer if several Employee instances share the same Boss.
If the lifetime of the data member isn't the same as the lifetime of the container, then include it by pointer: for example if the data member is instantiated after the container, or destroyed before the container, or destroyed-and-recreated during the lifetime of the container, or if it ever makes sense for the data member to be null.
Another time when you must including by pointer (or by reference) instead of by value is when the type of the data member is an abstract base class.
Another reason for including by pointer is that that might allow you to change the implementation of the data member without recompiling the container. For example, if Car and Carburetor were defined in two different DLLs, you might want to include Carburetor by pointer: because then you might be able to change the implementation of the Carburetor by installing a different Carburetor.dll, without rebuilding the Car.dll.

I tend to prefer the first case because the second one requires you to #include Carburettor.h in Car.h.
Since Carburettor is a private member you should not have to include its definition somewhere else than in the actual Car implementation code. The use of the Carburettor class is clearly an implementation detail and external objects that use your Car object should not have to worry about including other non mandatory dependencies. By using a pointer you just need to use a forward declaration of Carburettor in Car.h.

Composition: prefer member when possible. Use a pointer when polymorphism is needed or when a forward declaration is used. Of course, without smart pointer, manual memory management is needed when using pointers.

If Carb has the same lifetime as Car, then the non-pointer form is better, in my opinion. If you have to replace the Carb in Car, then I'd opt for the pointer version.

Generally, the non-pointer version is easier to use and maintain.
But in some cases, you can't use it. For example if the car has multiple carburetors and you wish to put them in an array, and the Carburetor constructor requires an argument: you need to create them via new and thus store them as pointers.

Related

C++ how to create a array of subclass use baseclass

suppose I have three class like these:
class base {
//some data
method();
};
class sub1 : base {
//some data
//overrides base method
method();
};
class sub2: base {
//some data
//overrides base methods
method();
};
How can I create a array mixed with sub1 and sub2? then calling subclass method with base?
Ok, let's sort this out. First of all, you probably meant virtual method();, probably with a return type, maybe with parameters. Without virtual, base class pointers and references won't know about the overridden method. Second, make the destructor virtual. Do this until you know why you need to (delete (base*) new derived;) - then keep doing this until all your neighbourhood knows why you need to. Third, the sad thing is, all std. C++ containers are homogeneous (non-std. heterogeneous container-like objects in Boost exist), thus you need to find an object that's common and that's somehow able to handle these types. Common choices are:
Common base class pointer, in your case, base*. This conventionally owns the objects and is manually (de)allocated (that is, you need to call new and delete). This is the most common choice. You might try smart pointers later, but let's get the basics first.
Common base class reference, in your case, base&. Common convention is that this doesn't own the object (albeit this is not a language restriction), thus it's mainly used for referring to objects that are stored in another container. Since you need to store them somewhere, I wouldn't opt for this now, but it might come handy later.
std::variant<> (or boost::variant<>), this is a discriminated union, that is, a class that stores one and only one of the listed items and knows which one it stores. You don't need a common base class, but even if you have one, it's cool because it tends to store objects locally, thus might be faster when you have enough cache.
union, which is like variant, but does not know the type being stored. Local storage is guaranteed, as well as UB if you write one field and read another
Compiler-specific solutions. If you know that your classes are of the same size (in this case, they are) and you know for sure that you have untyped memory, then you might store the base class and it'll 'just work', provided you always take the address and -> operator. Note that this is UB squared, I just list this because you'll likely encounter similar code. Also note that simply having a union does not remove UB in this case - until we have access to virtual table pointer, this can only be done by manually handling virtual functions.

C++:using pointer to unordered_map or just defining it as a member variable from this type in a class?

I have a problem which I cannot understand:
Let's Say I have a class System with several member fields, and one of them is of type unordered_map, so when I declare the class in the header file, I write at the beginning of the header #include <unordered_map>.
Now, I have two ways of declaring this field:
1.std::unordered_map<std::string,int> umap;
2.std::unordered_map<std::string,int>* p_umap;
Now in the constructor of the class, if I choose the first option, there is no need to initialize that field in the initializer list since the constructor of class System will call the default constructor for the field umap as part of constructing an instance of type class System.
If I choose the second option, I should initialize the field p_umap in the constructor (in the initialize list) with the operator new and in the destructor, to delete this dynamic allocation.
What is the difference between these two options? If you have a class that one of it's fields is of type unordered_map, how do you declare this field? As a pointer or as a variable of type unordered_map?
In a situation like the one you are describing, it seems like the first option is preferable. Most likely, in fact, the unordered map is intended to be owned by the class it is a data member of. In other words, its lifetime should not be extended beyond the lifetime of the encapsulating class, and the encapsulating class has the responsibility of creating and destroying the unordered map.
While with option 1 all this work is done automatically, with option 2 you would have to take care of it manually (and take care of correct copy-construction, copy-assignment, exception-safety, lack of memory leaks, and so on). Surely you could use smart pointers (e.g. std::unique_ptr<>) to encapsulate this responsibility into a wrapper that would take care of deleting the wrapped object when the smart pointer itself goes out of scope (this idiom is called RAII, which is an acronym for Resource Acquisition Is Initialization).
However, it seems to me like you do not really need a pointer at all here. You have an object whose lifetime is completely bounded by the lifetime of the class that contains it. In these situations, you should just not use pointers and prefer declaring the variable as:
std::unordered_map<std::string, int> umap;
Make it not a pointer until you need to make it a pointer.
Pointers are rife with user error.
For example, you forgot to mention that your class System would also need to implement
System( const Sysytem& )
and
System& operator= ( const System& )
or Bad Behavior will arise when you try to copy your object.
The difference is in how you want to be able to access umap. Pointers can allow for a bit more flexibility, but they obviously add complexity in terms of allocation (stack vs heap, destructors and such). If you use a pointer to umap, you can do some pretty convoluted stuff such as making two System's with the same umap. In the end though, go with KISS unless there's a compelling reason not to.
There is no need to define it as pointer. If you do it, you must also make sure to implement copy constructor and assignment operator, or disable them completely.
If there is no specific reason to make it a pointer (and you don't show any) just make it a normal member variable.

Should I store a completely incapsulated member by reference, by value or by ptr?

So I have the standard C++ setup with an object that stores another object. The stored object is owned completely, it's never leaked to the outside. The member is non-const.
class Container
{
private:
Contained item;
}
As I understand, when my Container is instantiated the default constructor will be called on the item member and I don't have to manage it in the initializer list.
Also do I understand it correctly that when my object is destroyed the dtor on the item will be called automatically?
Another option would be to store it by reference of course
class Container
{
private:
Contained& item;
public:
Container() : Contained()
{
}
}
in which case I don't know whether I should delete it in the dtor.
Yet another option is to store it by ptr
class Container
{
private:
Contained* item;
public:
Container()
{
item = new Contained();
}
~Container()
{
delete item;
}
}
Knowing that my item never gets returned to the caller and never bleeds into the outside API and never gets reassigned, what is the best way to proceed? As I mentioned, the item member is not const
(it will be a self-resizing data structure).
The easiest is to store the object itself. Using reference for this purpose is, I would say, confusing. One advantage with using the pointer is that you then may be able to avoid defining the Contained type in the header file - you can instead forward declare Contained, and keep all the details inside the .cpp file.
The first way is the best way in my opinion (it appears you don't need the object to be lazily constructed). The second way requires that you pass in the object from the outside and that it's lifetime is guaranteed, and the third way is really only good if you want lazy instantiation (i.e. only create the object on first use).
In this case, it's best to store the object itself, yes. Storing it by reference will only create an alias to the object, so your class is not the actual owner. Storing via a pointer is useless, unless your object is a base class and you might want to store a derived object.
Contrary to Luchian Grigore, I’d go for pointer/reference method: storing the encapsulated object as a reference or pointers lets you forward-declare it, hence saving compilation time.
In addition to that, it lets you have init() and destroy() member functions that would in turn call the constructor and destructors of the encapsulated object, as well as perform initialization of the other parts of the object. This way, a bad initialization can be handled by the return value of init().
Most of the time, you want to reduce the dependencies on your class. If this class forms an integral part of the interface (even if the member is private) then you can assume that anyone using your class will be using this one.
In such a case, having it as a member variable makes sense.
Where it is an implementation detail of your class, you should hide this detail from the users by using a forward declaration, so use a type that allows a forward declaration.
It is highly unlikely that it will be a reference. A reference must be initialsed on construction of your class, and so the constructor would probably have to pass in the object it refers to. Declaring it with new and dereferencing is going to lead to confusion.
If it is a pointer, your class can manage its lifetime with the destructor. In this case I often will use a raw pointer as it is well under control and my destructor can happily delete it, assuming my class is non-copyable.
If you use shared_ptr, you can use a forward declaration. But beware that your semantics are now that if you copy your object, all the copies will have a pointer to the same underlying object. If this is not what you want, shared_ptr is probably wrong. In addition, if you use shared_ptr when your class is non-copyable, it isn't really shared.
So unless you can use unique_ptr which allows a forward declaration, I would go for the raw pointer and a non-copyable class.
If your member does remain an implementation detail but is something that is pretty standard, like a map or a vector, it is not worth "encapsulating it" to the extent of using a forward declaration, only the types that are contained within the map or the vector, but not the map or vector itself.

C++ - when should I use a pointer member in a class

One of the thing that has been confusing for me while learning C++ (and Direct3D, but that some time ago) is when you should use a pointer member in a class. For example, I can use a non-pointer declaration:
private:
SomeClass instance_;
Or I could use a pointer declaration
private:
Someclass * instance_
And then use new() on it in the constructor.
I understand that if SomeClass could be derived from another class, a COM object or is an ABC then it should be a pointer. Are there any other guidelines that I should be aware of?
A pointer has following advantages:
a) You can do a lazy initialization, that means to init / create the object only short before the first real usage.
b) The design: if you use pointers for members of an external class type, you can place a forward declaration above your class and thus don't need to include the headers of that types in your header - instead of that you include the third party headers in your .cpp - that has the advantage to reduce the compile time and prevents side effects by including too many other headers.
class ExtCamera; // forward declaration to external class type in "ExtCamera.h"
class MyCamera {
public:
MyCamera() : m_pCamera(0) { }
void init(const ExtCamera &cam);
private:
ExtCamera *m_pCamera; // do not use it in inline code inside header!
};
c) A pointer can be deleted anytime - so you have more control about the livetime and can re-create an object - for example in case of a failure.
The advantages of using a pointer are outlined by 3DH: lazy initialization, reduction in header dependencies, and control over the lifetime of the object.
The are also disadvantages. When you have a pointer data member, you probably have to write your own copy constructor and assignment operator, to make sure that a copy of the object is created properly. Of course, you also must remember to delete the object in the destructor. Also, if you add a pointer data member to an existing class, you must remember to update the copy constructor and operator=. In short, having a pointer data member is more work for you.
Another disadvantage is really the flip side of the control over the lifetime of the object pointed to by the pointer. Non-pointer data members are destroyed automagically when the object is destroyed, meaning that you can always be sure that they exist as long as the object exists. With the pointer, you have to check for it being nullptr, meaning also that you have to make sure to set it to nullptr whenever it doesn't point to anything. Having to deal with all this may easily lead to bugs.
Finally, accessing non-pointer members is likely to be faster, because they are contiguous in memory. On the other hand, accessing pointer data member pointing to an object allocated on the heap is likely to cause a cache miss, making it slower.
There is no single answer to your question. You have to look at your design, and decide whether the advantages of pointer data members outweigh the additional headache. If reducing compile time and header dependencies is important, use the pimpl idiom. If your data member may not be necessary for your object in certain cases, use a pointer, and allocate it when needed. If these do not sound like compelling reasons, and you do not want to do extra work, then do not use a pointer.
If lazy initialization and the reduction of header dependencies are important, then you should first consider using a smart pointer, like std::unique_ptr or std::shared_ptr, instead of a raw pointer. Smart pointers save you from many of the headaches of using raw pointers described above.
Of course, there are still caveats. std::unique_ptr cleans up after itself, so you do not need to add or modify the destructor of your class. However, it is non-copiable, so having a unique pointer as a data member makes your class non-copiable as well.
With std::shared_ptr, you do not have to worry about the destructor or copying or assignment. However, the shared pointer incurs a performance penalty for reference counting.
Allocate it on the stack if you can, from the free-store if you have to. There is a similar question here, where you will find all the "why's".
The reason you see lots of pointer usage when it comes to games and stuff is because DirectX is a COM interface, and in honesty, most games programmers from back in the day aren't really C++ programmers, they are C-with-classes programmers, and in C pointer usage is very common.
Another reason to use pointers would be dynamic binding. If you have a base class with a virtual method and some derived classes, you can only get dynamic binding using pointers.

Should I prefer pointers or references in member data?

This is a simplified example to illustrate the question:
class A {};
class B
{
B(A& a) : a(a) {}
A& a;
};
class C
{
C() : b(a) {}
A a;
B b;
};
So B is responsible for updating a part of C. I ran the code through lint and it whinged about the reference member: lint#1725.
This talks about taking care over default copy and assignments which is fair enough, but default copy and assignment is also bad with pointers, so there's little advantage there.
I always try to use references where I can since naked pointers introduce uncertaintly about who is responsible for deleting that pointer. I prefer to embed objects by value but if I need a pointer, I use auto_ptr in the member data of the class that owns the pointer, and pass the object around as a reference.
I would generally only use a pointer in member data when the pointer could be null or could change. Are there any other reasons to prefer pointers over references for data members?
Is it true to say that an object containing a reference should not be assignable, since a reference should not be changed once initialised?
My own rule of thumb :
Use a reference member when you want the life of your object to be dependent on the life of other objects : it's an explicit way to say that you don't allow the object to be alive without a valid instance of another class - because of no assignment and the obligation to get the references initialization via the constructor. It's a good way to design your class without assuming anything about it's instance being member or not of another class. You only assume that their lives are directly linked to other instances. It allows you to change later how you use your class instance (with new, as a local instance, as a class member, generated by a memory pool in a manager, etc.)
Use pointer in other cases : When you want the member to be changed later, use a pointer or a const pointer to be sure to only read the pointed instance. If that type is supposed to be copyable, you cannot use references anyway. Sometimes you also need to initialize the member after a special function call ( init() for example) and then you simply have no choice but to use a pointer. BUT : use asserts in all your member function to quickly detect wrong pointer state!
In cases where you want the object lifetime to be dependent on an external object's lifetime, and you also need that type to be copyable, then use pointer members but reference argument in constructor That way you are indicating on construction that the lifetime of this object depends on the argument's lifetime BUT the implementation use pointers to still be copyable. As long as these members are only changed by copy, and your type don't have a default constructor, the type should fullfil both goals.
Avoid reference members, because they restrict what the implementation of a class can do (including, as you mention, preventing the implementation of an assignment operator) and provide no benefits to what the class can provide.
Example problems:
you are forced to initialise the reference in each constructor's initialiser list: there's no way to factor out this initialisation into another function (until C++0x, anyway edit: C++ now has delegating constructors)
the reference cannot be rebound or be null. This can be an advantage, but if the code ever needs changing to allow rebinding or for the member to be null, all uses of the member need to change
unlike pointer members, references can't easily be replaced by smart pointers or iterators as refactoring might require
Whenever a reference is used it looks like value type (. operator etc), but behaves like a pointer (can dangle) - so e.g. Google Style Guide discourages it
Objects rarely should allow assign and other stuff like comparison. If you consider some business model with objects like 'Department', 'Employee', 'Director', it is hard to imagine a case when one employee will be assigned to other.
So for business objects it is very good to describe one-to-one and one-to-many relationships as references and not pointers.
And probably it is OK to describe one-or-zero relationship as a pointer.
So no 'we can't assign' then factor.
A lot of programmers just get used with pointers and that's why they will find any argument to avoid use of reference.
Having a pointer as a member will force you or member of your team to check the pointer again and again before use, with "just in case" comment. If a pointer can be zero then pointer probably is used as kind of flag, which is bad, as every object have to play its own role.
Use references when you can, and pointers when you have to.
In a few important cases, assignability is simply not needed. These are often lightweight algorithm wrappers that facilitate calculation without leaving the scope. Such objects are prime candidates for reference members since you can be sure that they always hold a valid reference and never need to be copied.
In such cases, make sure to make the assignment operator (and often also the copy constructor) non-usable (by inheriting from boost::noncopyable or declaring them private).
However, as user pts already commented, the same is not true for most other objects. Here, using reference members can be a huge problem and should generally be avoided.
As everyone seems to be handing out general rules, I'll offer two:
Never, ever use use references as class members. I have never done so in my own code (except to prove to myself that I was right in this rule) and cannot imagine a case where I would do so. The semantics are too confusing, and it's really not what references were designed for.
Always, always, use references when passing parameters to functions, except for the basic types, or when the algorithm requires a copy.
These rules are simple, and have stood me in good stead. I leave making rules on using smart pointers (but please, not auto_ptr) as class members to others.
Yes to: Is it true to say that an object containing a reference should not be assignable, since a reference should not be changed once initialised?
My rules of thumb for data members:
never use a reference, because it prevents assignment
if your class is responsible for deleting, use boost's scoped_ptr (which is safer than an auto_ptr)
otherwise, use a pointer or const pointer
I would generally only use a pointer in member data when the pointer could be null or could change. Are there any other reasons to prefer pointers over references for data members?
Yes. Readability of your code. A pointer makes it more obvious that the member is a reference (ironically :)), and not a contained object, because when you use it you have to de-reference it. I know some people think that is old fashioned, but I still think that it simply prevent confusion and mistakes.
I advise against reference data members becasue you never know who is going to derive from your class and what they might want to do. They might not want to make use of the referenced object, but being a reference you have forced them to provide a valid object.
I've done this to myself enough to stop using reference data members.