Reputation: 278
Bar and Box are derived classes of Foo and Foo has a virtual function F() and Bar and Box both have function F(). From what I understand, polymorphism correctly allows Bar.F() instead of Box.F() or Box.F() instead of Bar.F() to override Foo.F() using some runtime routine without knowing whether your object is a Bar or a Box. It's something like this:
Foo * boxxy = new Box;
boxxy->F();
The last line will call the right F() (in this case, Box.F()) independent of whether boxxy is a Box or a Bar or a Foo (in which case the implementation of the virtual Foo.F() is called).
Do I understand this right? And what changes if boxxy is a Box pointer? And what happens if the derived class doesn't have an override for F()? Lastly, to avoid implementing a function for a base class but still allow polymorphism, do you just write an empty function body and declare it virtual? Thanks.
Upvotes: 2
Views: 326
Reputation: 131779
Nearly right - consider this inheritance tree:
Foo
/ \
Bar Box
If you now make a pointer like this:
Bar* barry = new Box();
You'll get a nice compiler error, since a Box
can't be converted to a Bar
. :)
So it's only Foo<->Bar
and Foo<->Box
, never Bar<->Box
.
Next, when boxxy
is a Box
pointer, it will only ever call the Box::F
function, if it is provided.
And last, to force subclasses to implement a certain function, you declare it pure virtual
, like this:
virtual void Func() = 0;
// note this --- ^^^^
Now subclasses (in this case Bar
and Box
), must implement Func
, else they will fail to compile.
Upvotes: 2
Reputation: 473
If you declare Foo like this
class Foo
{
private:
Foo() {};
public:
void func() const { std::cout << "Calling Foo::func()" << std::endl; }
};
and Bar like this
class Bar : public Foo
{
private:
Bar() {};
public:
void func() const { std::cout << "Calling Bar::func()" << std::endl; }
};
then
Foo* bar = new Bar();
bar->func();
will call Foo::func().
If you declare Foo like this
class Foo
{
private:
Foo() {};
public:
virtual void func() const { std::cout << "Calling Foo::func()" << std::endl; } // NOTICE THE virtual KEYWORD
};
then
Foo* bar = new Bar();
bar->func();
will call Bar::func().
Upvotes: 1
Reputation: 14943
And what changes if boxxy is a Box pointer?
It will allow access to the methods of Box not inherited from Foo. Box pointer can't point to Bar objects, since Bar isn't derived from Box.
And what happens if the derived class doesn't have an override for F()?
It will inherit the implementation of F() from the base class.
Lastly, to avoid implementing a function for a base class but still allow polymorphism, do you just write an empty function body and declare it virtual?
It will work, but it is not a right way to do polymorphism. If you can't come up with a concrete implementation for the virtual function of the base class make that function pure virtual, don't implement it as empty function.
Upvotes: 1
Reputation: 63190
Yes the right F() will be called dependent on the type of object you have created through your Foo pointer.
If boxxy were a Box pointer you could only call it's F() or one of it's derived class's F(), unless you did a dynamic_cast to it's parent class and then called F().
To avoid having to implement in the base class you define it as pure virtual like so:
class Foo
{
public:
virtual void F() = 0; //notice the = 0, makes this function pure virtual.
};
Upvotes: 1
Reputation: 308101
virtual void F() = 0
. Any
class that intends to be instantiated
into an object much override this
function and give it a proper
implementation.Upvotes: 0