tags:

views:

104

answers:

4

I'm a bit confused:

  • If I have a base class A, and a class B which extends A, can a variable of the type A hold a value of the type B and vice versa?

If yes, why? Aren't they completely different even if B is derived from A? How about type-safety?

  • If this is possible, what things do I have to mind when taking use of this? How would this work out in terms of performance?

Note: Sorry if I asked too many questions, just ignore them and just look out for those "marked" with the list decoration dot :) Also, this is not my homework. I'm a hobby programmer and have skills in scripting languages with OOP, yet I'm relatively new to OOP typing in C++.

+3  A: 

If you do this:

B b;
A a = b;

then you get "slicing". a will contain just the A part of b.

But you can have references/pointers:

B b;
A &ra = b;
A *pa = &b;

In this case, ra and pa just refer/point to the real B object. This is because public inheritance models an IS-A relation. This is easier to understand with more descriptive names. Think of A and Animal and B as Baboon. A Baboon IS-A Animal so by using references/pointers, you can treat a Baboon as it's more generic Animal type.

R Samuel Klatchko
Could you maybe explain how and why this works with pointers? Why doesn't C++ cry out for a typing error? I mean A != B, or?
Zack
`A` and `B` are types, not objects (unlike many other languages where types are objects). With pointers, an `A*` can refer to anything derived from A, and the virtual functions will get correctly forwarded to the derived class implementation. E.g. `Animal* animal = new Baboon(); animal->Eat(); animal->Sleep();` will call the Baboon class's Eat and Sleep methods if they're virtual (in Animal) and overridden in Baboon. OTOH, if you did `Animal a = Baboon();`, a Baboon will get created, but then *sliced* and you'll be left with a valid Animal that contains nothing extra from Baboon.
dash-tom-bang
A: 

A variable of type A can hold a value of type B (for certain definitions of "hold", as other answers explain), but definitely not vice-versa. To break out a standard example:

class Animal {};
class Dog : public Animal {};
class Cat : public Animal {};

This is legal, because Cat derives from Animal:

Cat c;
Animal& a = c;

This isn't:

Animal a;
Cat& c = a;

This is type-safe because you've defined it to be so; the whole point of inheritance is to allow this sort of thing to happen, so you can go on to call methods on a generic Animal variable without knowing what base class happens to be stored in it. As for the performance question, calling virtual methods is slower because deciding which method will actually be called (Cat::foo() versus Dog::foo(), for example, depending on the particular type of Animal stored in the variable) has to happen at run-time -- this is called dynamic dispatch. With non-virtual methods the decision can happen at compile time

Michael Mrozek
In C++ the variable you're assigning to needs to be a reference (your code will compile, but it won't run as you expect). The code should be `Cat c; Animal` and `Animal a; Cat`. See the other answers.
Ken Bloom
It may be legal but it isn't very useful. As Ken said, use references (or pointers).
jmucchiello
A: 

A pointer or reference to an object of class A can point/refer to an object of class B. That's because if B derives from A, then a B is-a A. Each object of class B has all the member variables and functions of class A, plus those unique to B.

class A
{
   public:
      virtual ~A();
      void foo();
};

class B : public A
{
   public:
      void bar();
};

A * a = new B;
a->foo(); // perfectly valid, B inherits foo() from A
//a->bar(); // compile-time error, bar() is only defined in B
delete a; // make sure A has a virtual destructor!

Usually, this sort of code is used when you want to make use of polymorphic behavior through virtual functions.

Nick Meyer
A: 

Not to be contrary, but performance is not the right question here. If you've decided that you're going to make an OO design, don't sacrifice the correct abstraction for performance concerns. Premature optimization is the root of all evil. Good luck!

leo grrr