C++ Do I Understand Polymorphism Correctly? - c++

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.

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.

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.
};

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.

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().

Do I understand this right? Yes, if the function was declared as a virtual function.
And what changes if boxxy is a Box
pointer? Depends on whether the
function is virtual or not. A virtual
function will always end up calling
the proper derived function; a
non-virtual function will call the
version based on the type of the
pointer.
And what happens if the derived class
doesn't have an override for F()? It
will use the base class definition.
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? You can also declare it pure
virtual: virtual void F() = 0. Any
class that intends to be instantiated
into an object much override this
function and give it a proper
implementation.

Related

what is the way of overriding a method in some code

Suppose we have the following code:
class Base
{
public:
virtual void foo() const
{ cout << "In Base::foo\n"; }
}
class Derived : public Base
{public:
virtual void foo()
{ cout << "In Derived::foo\n"; }
}
void main()
{
Base* b = new Derived();
b->foo();
delete b;
}
It will give us the following output: In Base::foo.
Now suppose I want to get - without changing the main function - the follwing output instead the one given above:
In Derived::foo
As far as I understand, I should override the function foo() of in the base, to get the output of the method
foo() in the inheriting class which is class 'Derived'.
But the problem is that in that case I can't using the command override, becuase the method in the base is defined as constant , which in the other class it is not.
So, how should I if then overriding that method ?
In order to override the function void foo() const of the base class, you must declare the function void foo() const in the derived class. You've declared the function void foo() instead (note the lack of const), which doesn't override the function in the base, because it has a different declaration.
So, how should I if then overriding that method ?
Add the missing const qualifier.
P.S. Few other bugs in your program:
main must return int.
Class definitions must end in a semicolon.
Deleting a derived object through a pointer to base has undefined behaviour unless the destructor of the base is virtual.

Inheritance with an override function

I'm looking at some C++ example code, which effectively has the following:
class Foo : public mynamespace::Bar
{
public:
Foo()
{
// Do some stuff
}
void Delta() override
{
// Do some stuff
Bar::Delta();
}
};
I am having trouble understanding why the line Bar::Delta(); exists. Given that class Foo inherits class Bar, then surely when Foo::Delta() is called, this overrides anything existing in Bar::Delta(), and hence this line is redundant.
Or am I misunderstanding this whole inheritance thing? Maybe override doesn't override everything?
Bar::Delta();
is a function call. Isn't that what it looks like?
It's calling the base class version of Delta - by explicitly qualifying it as Bar::Delta - in addition to whatever extra stuff Foo's version does.
Maybe override doesn't override everything?
The override keyword just asks the compiler to verify you're really overriding a virtual function - otherwise, it's easy to accidentally write a new function which doesn't override anything (eg. because a parameter type is slightly different, or one version is const-qualified, or you changed the base class and forgot to update the derived class, or ...).
Here you are overriding the virtual function. That doesn't stop the base class implementation from existing, and as you've seen you can still call it.
You can (and should) test your intuition about this sort of thing yourself. Consider the trivial test code below. What do you think it will do?
Now actually run it. Were you right? If not, which part was unexpected?
#include <iostream>
using namespace std;
struct Bar {
virtual void Delta() {
cout << "Bar::Delta\n";
}
};
struct Foo : public Bar {
void Delta() override
{
cout << "Foo::Delta\n";
Bar::Delta();
}
};
int main()
{
cout << "b.Delta()\n";
Bar b;
b.Delta();
cout << "f.Delta()\n";
Foo f;
f.Delta();
cout << "pb->Delta()\n";
Bar *pb = &b;
pb->Delta();
cout << "pb->Delta()\n";
pb = &f;
pb->Delta();
}
This is a common pattern. In fact, the :: syntax for calling an overridden member function is there specifically for this situation.
It is very common for member function in a base class to perform some computation or action which can be done independently of the derived class, and let the derived class do things specific to the derivation.
Here is a fictitious example:
class Stock {
protected:
double totalDividend;
double baseDividend;
double adjustmentFactor;
public:
Stock(double d, double a)
: baseDividend(d), totalDividend(d), adjustmentFactor(a) {
}
virtual void double ComputeDividend() {
return totalDividend * adjustmentFactor;
}
};
class SpecialStock {
private:
double specialDividend;
public:
SpecialStock(double d, double sd, double a)
: Stock(d, a), specialDividend(sd) {
}
virtual void double ComputeDividend() override {
// Do some preparations
totalDividend = baseDividend + specialDividend;
// Call the overridden function from the base class
return Stock::ComputeDividend();
}
};
You seem to misunderstand what override means in c++. You should not really bother by it for your case. It's like a normal virtual function. override keyword is just a safety mechanism to ensure that a base class has matching function. It doesn't change anything other than semantic compile-time checks.
It is somewhat useful to guard against typical mismatches, such a const vs non-const versions, etc.
The virtual method mechanism does not replace the original member functions. It still is there in the Derived object. What happens is that a level of indirection is introduced, so a call to base.foo() uses a function pointer to call correct implementation which is Derived::Foo() in your case. But Base::Foo() still exists, and this is the syntax to "access" it. You can look up how exactly it work by searching materials on virtual methods.
Maybe override doesn't override everything?
The override specifier can be used to make compile-time checks when overriding a function that the function being overridden is virtual and is in fact being overridden.
why the line Bar::Delta(); exists
This line calls the base Delta function which might have some useful tasks to perform even though you have overridden it.
A simple example:
class Base
{
public:
virtual ~Base() {}
virtual void Foo()
{
// run tasks that are common to all derived types
}
};
class Derived : public Base
{
public:
void Foo() override
{
Base::Foo(); // we have to call this explicitly
// run tasks specific to the derived type
}
};
Delta in foo is a virtual method which "does some stuff" and then calls the base class's implementation of Delta.
override does not override anything, declaring the method as virtual does that. override is just for the compiler to throw syntax error in case the parent class doesn't have the Delta method.

Function overriding in C++ works without 'virtual'

I have a class that contains some functions (none are virtual) and 2 more classes publicly inherit that class. In both the sub classes I override the same function of the base class.
After creating objects of all three classes in main (located at the same file), I call the original function with the baseclass object and the overridden functions with the derivedclass objects.
I was expecting all 3 function calls to run the original function from the base class (since I didn't use 'virtual' anywhere in the code), but I actually get each version of that function working according to the class in which it was defined (3 different versions).
I have the classes Base & Derived as follows:
struct Base
{
void foo();
};
struct Derived : Base
{
void foo();
};
in main:
int main()
{
Derived d;
d.foo();
}
I thought d.foo() should run Base::foo() if not using 'virtual'.
This is not "overriding"... and it doesn't need to be.
struct Base
{
void foo();
};
struct Derived : Base
{
void foo();
};
int main()
{
Derived d;
d.foo();
}
If I understand you correctly, then you were expecting this to execute Base::foo(), because the functions are not virtual and therefore one does not override the other.
But, here, you do not need virtual dispatch: the rules of inheritance simply state that you'll get the right function for the type of the object you run it on.
When you need virtual dispatch/overriding is a slightly different case: it's when you use indirection:
int main()
{
Base* ptr = new Derived();
ptr->foo();
delete ptr;
}
In the above snippet, the result will be that Base::foo() is called, because the expression ptr->foo() doesn't know that *ptr is really a Derived. All it knows is that ptr is a Base*.
This is where adding virtual (and, in doing so, making the one function override the other) makes magic happen.
You cannot override something that isn't virtual. Non-virtual member functions are dispatched statically based on the type of the instance object.
You could cheat by "overriding" a function by making it an inline function calling something indirectly. Something like (in C++03)
class Foo;
typedef int foo_sig_t (Foo&, std::string&);
class Foo {
foo_sig_t *funptr;
public:
int do_fun(std::string&s) { return funptr(*this,s); }
Foo (foo_sig_t* fun): funptr(fun) {};
~Foo () { funptr= NULL; };
// etc
};
class Bar : public Foo {
static int barfun(Bar&, std::string& s) {
std::cout << s << std::endl;
return (int) s.size();
};
public:
Bar () : Foo(reinterpret_cast<foo_sig_t*>)(&barfun)) {};
// etc...
};
and later:
Bar b;
int x=b.do_fun("hello");
Officially this is not overloading a virtual function, but it looks very close to one. However, in my above Foo example each Foo instance has its own funptr, which is not necessarily shared by a class. But all Bar instances share the same funptr pointing to the same barfun.
BTW, using C++11 lambda anonymous functions (internally implemented as closures), that would be simpler and shorter.
Of course, virtual functions are in generally in fact implemented by a similar mechanism: objects (with some virtual stuff) implicitly start with a hidden field (perhaps "named" _vptr) giving the vtable (or virtual method table).

Virtual function call from a normal function

class base
{
public:
void virtual func(){cout<<"base";}
void check()
{
func();
}
};
class derived: public base
{
public:
void func(){cout<<"dervied";}
};
int main()
{
base *obj = new derived();
obj->check();
return 0;
}
Above code prints derived on the console.
Now, I understand the concept of virtual functions but I'm unable to apply it here. In my understanding whenever we call a virtual function, compiler modifies the call to "this->vptr->virtualfunc()" and that's how most heavily derived's class function gets invoked. But in this case, since check() is not a virtual function, how does the compiler determine that it needs to invoke func() of derived?
how does the compiler determine that it needs to invoke func() of derived?
In the same exat way - by invoking this->vptr->virtualfunc(). Recall that this belongs to the derived class even inside the base class, because each derived class is a base class as well, so the same way of accessing virtual functions works for it too.
Exactly the way you said, by using the vptr in the class member. It knows the function is virtual, therefore it knows it has to call it through the virtual function table.

If an overridden C++ function calls the parent function, which calls another virtual function, what is called?

I'm learning about polymorphism, and I am confused by this situation:
Let's say I have the following C++ classes:
class A{
...
virtual void Foo(){
Boo();
}
virtual void Boo(){...}
}
class B : public A{
...
void Foo(){
A::Foo();
}
void Boo(){...}
}
I create an instance of B and call its Foo() function. When that function calls A::Foo(), will the Boo() method used be that of class A or B? Thanks!
Unless you qualify a function call with the class, all method calls will be treated equal, that is dynamic dispatch if virtual, static dispatch if not virtual. When you fully qualify with the class name the method you are calling you are effectively disabling the dynamic dispatch mechanism and introducing a direct method call.
class A{
virtual void Foo(){
Boo(); // will call the final overrider
A::Boo(); // will call A::Boo, regardless of the dynamic type
}
virtual void Boo();
};
class B : public A{
void Foo(){
//Foo(); // Would call the final overrider
// (in this case B: infinite recursion)
A::Foo(); // Will call A::Foo, even if the object is B
}
void Boo();
};
The implicit this pointer is not an important part of the discussion here, as exactly the same happens when the call is made with an explicit object:
B b;
b.Foo(); // will call B::Foo -- note 1
b.A::Foo(); // will call A::Foo
Note 1: in this example, the compiler can elide the dynamic dispatch mechanism as it knows the concrete type of the instance (it sees the definition and it is not a reference/pointer) but you can imagine the same would happen if b was a reference, or equivalently if it was a pointer with -> instead of .
Since Boo() is virtual, the derived class' override is called.
Boo(); is just a short-hand for this->Boo();, where you can see that a virtual function is called through a pointer. (this is of type A* const within Foo().) And virtual functions called through a reference or a pointer will always call the override in the most-derived class (except when called from a constructor or destructor).
Inside A,
virtual void Foo(){
Boo();
}
gets translated to this->Boo() ;since Boo is declared virtual in A, the derived class's method Boo gets called. Try not declaring Boo as virtual in A just for experimentation -- you'd see that A->Boo() is getting called.
Arpan