General c++ questions on polymorphism & composition

After the end of my first c++ course , I have some questions that I'd like to discuss with you guys :)

1.Why would we ever want to upcast (or use upcasting) ? after having a few homework regarding the matter of polymorphism , I do find it a very strong mechanism for allowing an object to behave differently , but still , why would I want to use the upcasting mechanism ?

2.When would we use private inheritance and when would choose composition ? private inheritance seals , in a way, the chain of inheritance , so the grandson won't be able to access any fields of the father , after
we do : class Father : private GrandFather {...}

3.When would we prefer inheritance over composition ? I think that if we ever would want to upcast , we must use inheritance (so ask ourselves the question "would we ever want to upcast" ) ?

4.What is the use of putting the copy-constructor in the private ? I think it comes handy when we do something like
a shallow copy , so if we have an object that has a dynamic allocation
1
2
class A{public: char * myStringChar;} 
A a; A b = a;

so here "a" and "b" would point to the same address in memory , and if we didn't write a proper cctor (i.e with
the use of "new") then both of them would point the same address .

5.Why cctor (copy constructor) cannot be virtual ?
is it because of the same reason that the Ctor can't be virtual ? because while the object's creation its (the object's) ctor is called , and its Vtable is not done yet , therefore the ctor can't be in the Vtable (would be ready after the ctor is done creating the object...)

6.Why a destructor cannot be overloaded ? of course it can be virtual (for inheritance use and preventing memory leaks) , but what might be the reason that the language doesn't support overloaded destructors ?

Regards,Davi
Last edited on
I'll just answer some of these:

4) So that you can't copy the object. Some objects aren't supposed to be copied. Your example wouldn't work if the copy constructor was private.

5) Because the only time you can call it is at construction, when you actually know the type of the object.

6) Because the compiler would have no way of figuring which one you would want to call. In other words, the destructor's arguments/return value are both specified in the standard, so any "overloaded" versions of it would have the exact same signature, and thus be ambiguous anywhere.
Well I'll give 6 a shot and have to think about 1...5, but 6:

Ask yourself what a destructor does! It is called when your class stops existing. It is NOT called by the programmer but automatically. This automatic calling can't take arguments what so ever! always ~myClass( void )
3.When would we prefer inheritance over composition ? I think that if we ever would want to upcast , we must use inheritance (so ask ourselves the question "would we ever want to upcast" ) ?


The classic answer is if you are modelling after a is-a relationship you use inheritance as it is most natural. If you are modelling after a has-a relationship you use composition by value,pointer,reference.

As to upcast, personally for me I have not done it yet. If I have to upcast then my earlier program design has some problems which should be corrected instead. The only valid excuse is you use some other ppl library and you have no access to their source code, so you are forced to do a up-cast to achieve the behavoir you want.

Frankly speaking, I uses more composition than inheritance in C++,Java I also don't know why. Possibly my design is lean-ed heavily to has-a relationship design ? Hmmm....
1) The whole idea of inheritance is that you can write code that uses abstract interfaces. This allows your code to work with lots of different kinds of classes instead of just one kind of class.

Here's a simple example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void printsomestuff( ostream& outstream )  // take an abstract 'ostream'
{
  outstream << "Output some stuff to it" << endl;
}

int main()
{
  // because printsomestuff takes an abstract ostream, we can give it an object
  //  of ANY class derived from ostream.  It will work with all of them.

  // cout is from ostream:
  printsomestuff( cout );  // works, outputs to the console

  // ofstream (files) are also from ostream
  ofstream myfile("myfile.txt");
  printsomestuff( myfile );  // works, outputs to myfile.txt
}


Here, we are upcasting 'cout' and 'myfile' to the more general base class ostream. This makes the printsomestuff function usable with more kinds of objects.



2) 99% of the time you want composition. In all honesty, in my years of programming, I haven't run into a situation where I've had use of private inheritance.


3) As sohguanh mentioned, inheritance forms an "is a" relationship. Composition forms a "has a" relationship.

Some examples:

1
2
3
4
5
class Fruit
{};

class Apple : public Fruit   // an Apple "is a" Fruit, so it makes sense to inherit
{};
1
2
3
4
5
6
class Occupation { };

class Employee   // an Employee "has a" Occupation, so composition makes more sense
{
  Occupation job;
};
Topic archived. No new replies allowed.