C++ Inheritance and Function Overriding

C++ inheritance and function overriding

The term used to describe this is "hiding", rather than "overriding". A member of a derived class will, by default, make any members of base classes with the same name inaccessible, whether or not they have the same signature. If you want to access the base class members, you can pull them into the derived class with a using declaration. In this case, add the following to class Y:

using X::spray;

C++ - Overloading vs Overriding in Inheritance

In C++, any method in a derived class only overrides the method in the base class if their declarations match (I say "match" but I don't know the formal term for that). That is, all arguments must have the same type, and const qualification of this must be the same. If anything there mismatches, the method in the derived class hides all methods with the same name, instead of overriding. This is what the "ERROR" in your picture tries to tell you. So // overrides in a comment in that picture is incorrect and misleading.

Yes, many C++ teachers actually don't understand these somewhat obscure details.

BTW additionally, if you want to override, the method in your base class should be virtual; otherwise, polymorphism won't work. If it was not virtual, we also say that the derived-class method hides the base-class method. Here, however, the part about hiding has almost no meaning; what this term really wants to express is that you're not overriding.

In addition, overloading is, as you noticed, presence of several methods with the same name but different signatures. They should all be present in the derived class to be useful - if the derived class has only one method fa1, and the other fa1 are in the base, they will be hidden. However, there is syntax sugar which "copies" all fa1 from base to derived, disabling all that hiding semantics:

class A
{
public:
void fa1();
void fa1(int);
};

class B: public A
{
public:
using A::fa1;
void fa1(int, int);
};

...
B b;
b.fa1(); // calls A::fa1()
b.fa1(4); // calls A::fa1(int)
b.fa1(4, 8); // calls B::fa1(int, int)

The part about hiding is rarely, if ever, useful. When overriding, you should tell this to your compiler - use the override keyword for that. The compiler will then check that your code works as you intended.

class A
{
public:
virtual void fa1(int) {}
void fa2(int) {}
};

class B: public A
{
public:
void fa1(int) override {} // OK
void fa1() override {} // ERROR: doesn't really override - different signature
void fa2(int) override {} // ERROR: doesn't really override - not virtual in base
};

Overriding virtual functions and inheritance

Please be patient and read this to get answers to your questions.

Inheritance is a concept in which object of a class inherits the properties and behaviour of object of another class.

Basic Introduction

  • Parent class is also called as base class or super class.
  • Child class is also called as derived class or subclass.
  • An object of a derived class can be referenced through the base class.

For example

#include <iostream>
using namespace std;
class Base {};
class Derived : public Base {};
int main() {
Base *b = new Derived(); // This is completely valid
return 0;
}

Method Overriding in C++

Let's take a basic example

#include <iostream>
using namespace std;
class Base {
public:
void display() { cout << "Base display called\n"; }
};
class Derived : public Base {
public:
void display() { cout << "Derived display called\n"; }
};
int main() {
Base b;
b.display();
Derived d;
d.display();
Base *bptr = &d;
bptr->display();
return 0;
}

Output:

Base display called
Derived display called
Base display called

Now, from the above example you might have guessed that the derived class overrides the base class but this is not the case. The output (3rd line) shows that the base class function is called because the function is not virtual.

Virtual functions in C++

You can make any function of the class virtual by adding the "virtual" keyword at the start of the function.

Lets consider the virtual function example

#include <iostream>
using namespace std;
class Base {
public:
virtual void display() { cout << "Base display called\n"; }
};
class Derived : public Base {
public:
void display() { cout << "Derived display called\n"; }
};
int main() {
Base b;
b.display();
Derived d;
d.display();
Base *bptr = &d;
bptr->display();
return 0;
}

Output:

Base display called
Derived display called
Derived display called

By the above example(line 3 of the output), it is clear that you can achieve method overriding by using the virtual function mechanism in C++.

What is the effect of making a function virtual?

The difference between a normal function and a virtual function is that a normal function is resolved at compile time, also known as static binding, whereas the virtual function is resolved at run time, also known as dynamic binding or late binding. Which method to call (base class display or derived class display method) is resolved at run time since the base class display function is made virtual. You can dive deep into the virtual function mechanism by reading about v-table.

Answers to questions

  1. call(d). I don't quite understand why but it seems that call() can take derived classes of B as an argument.

    • A derived class object can be referenced by a base class
  2. But D::g doesn't override B::g and for the reasons I can't understand.

    • Because g() is not virtual in base class. Only virtual functions can be overridden. v-table has entries to only virtual functions so that they can be overridden at run time.
  3. call(dd)

    • Since f() in DD is a non-const function, therefore f() (non-const f() in DD) is not an overridden method of the parent class D. And since it is being referenced by Base class B, calling b.f() would call the const f() which is being overridden by D. Thus D::f gets printed.
    • If f() was a const method in DD then the following would have happened:
      When f() gets called, the function is searched first in the base class B,
      since f() is virtual, using the v-table pointer, the f() function being overridden in derived class D is resolved. But since f() is not virtual in class D, the overridden f() in DD can't be resolved. Hence D::f gets printed.

      But for g(), the base class itself doesn't have virtual g(), so the overridden functions in their derived classes can't be resolved. Hence, B::g get printed.
  4. The above polymorphism has happened because the derived classes were referenced by their base classes(parent classes), but in the last calls, there is no such thing. All the objects are referenced by their respective classes, and hence their appropriate methods are being called.

One basic logic to think about this is that the function is first looked up in the referencing class, and if it is virtual then the function will be searched in derived classes(if the object being referred is a child class). If the derived classes override, then the derived method will be called, else the base method will be called. You can further extend the concept applied to the base class, to the derived class as well like the check whether the function is virtual or not and then if the function is virtual and the object is derived(child of the derived, grandchild of the base) and so on.

Hope this clarifies.

C++ inheritance function override

I feel like there's two problems here for you. One is a syntactical problem, which others have already addressed. However, it seems that you also have an underlying problem of trying to write Java/C# code in C++. This will lead to misery no matter what the syntactical problems are, so I try to address this here.

In c++ when I do this with vector it calls that parent's function. How can I do the example above in C++?

Java and C# use the object-oriented paradigm for everything. C++ is different in that C++ is a multi-paradigm language. It supports (more or less) Structured, OO, Generic, Functional and whatnot Programming paradigms. You can freely mix and mingle paradigms, and C++ shines brightest where you do that.

The part of the standard library that derives from the STL, that is: containers, algorithms, iterators, are not OO at all. They are applying Generic Programming. One of the attributes of that is that the containers usually (there are exceptions, but not within the standard library itself) store values, rather than references. Polymorphism, however, at least runtime polymorphism, only operates on references (or, syntactically, pointers, which are, semantically, references, too).

If you have a std::vector<base_class> vc, this will store actual values, rather than references to objects somewhere on the heap. If you put an object into such a container, the object will actually be copied into the container. If you put in a derived_class object, then that is subjected to slicing. That is, only the base_class part of it will be copied into the container, all the derived_class parts will be disregarded. You then end up with an actual base_class object in the container, rather than, as in Java and C#, a base class reference to a derived class object somewhere on the heap.

That is why invoking a member function on that object will end up in the base class: there is no derived class object to invoke a function on.

In C++, if you want to employ OOP, you will usually have to dynamically allocate derived class objects (i.e., new derived_class()) and assign them to base class pointers. The problem with this is that C++ does not have garbage collection, so you must keep track of those pointers, and all the copies made from it, and explicitly delete the object just before the last pointer gets destroyed. That is very error-prone to do manually, which is why nowadays everybody lets smart pointers do this automatically.

So what you want is std::vector<smart_ptr<base_class>> and put in new derived_class() objects. What the symbolic smart_ptr refers to depends on your needs. If you plan to store pointers to those objects nowhere but in that container, std::unique_ptr (std::tr1::unique_ptr if your compiler only supports C++03, or boost::unique_ptr if it doesn't even support that) would be ideal. If you freely pass around such pointers, and them to keep track of when the last goes out of scope for themselves, std::shared_ptr would be better.


Now, all this said, I feel the need to add: You might not need to do this the OO way at all. There might be a much better design if you could just let go of the rigid OO thinking Java and C# have imprisoned you in.

If you employ polymorphism just so you can pass containers with different content to the same algorithms, then employing Generic Programming might be much better:

template<typename FwdIt>
void do_something(FwdIt begin, FwdIt end)
{
while(begin != end)
if(begin->foo() == bar()) // whatever
begin->baz(); // whatever
}

std::vector<some_class> vs;
std::vector<other_class> vo;
std::deque<other_class> do;

// ...

do_something(vs.begin(), vs.end());
do_something(vo.begin(), vo.end());
do_something(do.begin(), do.end());

This works for all types (here it's some_class) that have a foo() member not taking any arguments and returning something comparable with whatever bar() returns, and have a baz() member, not taking any arguments either. (If you try to use some type that doesn't have those, the compiler will bark at you.)

C++: How to override method of a specific class with same interface

You can always define intermediate classes that declare their own interfaces:

template<typename T>
struct Foo
{
virtual ~Foo() = default;
virtual void foo() = 0;
};

struct ProxyFooInt : public Foo<int>
{
virtual void fooInt() = 0;

void foo() override
{
return fooInt();
}
};

struct ProxyFooDouble : public Foo<double>
{
virtual void fooDouble() = 0;

void foo() override
{
return fooDouble();
}
};

struct Derived : public ProxyFooInt, public ProxyFooDouble
{
void fooInt() override
{
std::cout << "Foo<int>::foo()" << std::endl;
}

void fooDouble() override
{
std::cout << "Foo<double>::foo()" << std::endl;
}
};

A more advanced solution would be to use CRTP:

template<typename D>
struct CrtpFooInt : public Foo<int>
{
void foo() override
{
return static_cast<D*>(this)->fooInt();
}
};

template<typename D>
struct CrtpFooDouble : public Foo<double>
{
void foo() override
{
return static_cast<D*>(this)->fooDouble();
}
};

struct Derived : public CrtpFooInt<Derived>, public CrtpFooDouble<Derived>
{
void fooInt()
{
std::cout << "Foo<int>::foo()" << std::endl;
}

void fooDouble()
{
std::cout << "Foo<double>::foo()" << std::endl;
}
};

override in multilevel inheritance with intermediate derived class not having the function overriden

Once a parent class have marked a function as virtual, that "virtualness" stays. It doesn't matter how many levels of inheritance you have or if any intermediate classes doesn't override the function, once a function is made virtual the function will always be virtual.

So to answer your question: Yes it's possible to use Derived2::method1 through polymorphism. The code you show should work fine.

C++ inheritance function overriding

I try to make a short code to solve your problem, but I don't have it (using "g++ test.cpp -fpermissive" to compile)

#include <iostream>

using namespace std;

class Father
{
public:
void A(){
cout<<"Hello Father"<<endl;
}
};

class Son : public Father
{
};

class GrandSon : public Son
{
public:
void A()
{
cout<<"Hello GrandSon"<<endl;
}
};

void justPrint(const Son& a)
{
a.A();
}

int main(int argc, char* argv[])
{
GrandSon jeff;
justPrint(jeff);
return 0;
}

Maybe you have put A in private?


Output:
Hello Father

Mistake when overriding C++ virtual function

When you assign an object of derived class to an object of base class like that, you not achieving dynamic dispatch, you achieve slicing (all of the additional data members of SubFilter are lost)

  Filter choose_filter(){
SubFilter f;
return f;
}

Instead you should pass it by (safe) pointer or reference, like this:

  std::shared_ptr<Filter> choose_filter(){
return std::make_shared<SubFilter>();
}

int main(int argc, char* argv[]) {

auto f = choose_filter();
f->ehi();
return 0;
}


Related Topics



Leave a reply



Submit