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++.
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.
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.
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!
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
精彩评论