Overriding of const member function in C++ - c++

Consider the following code:
#include <iostream>
#include<string>
using namespace std;
class Base
{
public:
virtual string print() const
{
return "This is Base class";
}
};
class Derived : public Base
{
public:
virtual string print() const
{
return "This is Derived class";
}
};
void describe(Base p)
{
cout << p.print() << endl;
}
int main()
{
Base b;
Derived d;
describe(b);
describe(d);
return 0;
}
On executing this code, it gives the output as
This is Base class
This is Base class
I had couple of doubts in this program:
The function print in class Base is a const member function, hence after inheritance, when we try to override the definition of print in Derived class, why doesn't the compiler give an error.
In this program, how we can we pass a derived class object (d) to the function which expects an argument of data Type Base.
Even if we could somehow pass the derived class object to the function, why does it print "This is Base class" instead of "This is Derived Class".
Does implicit type-conversion take place when I pass a derived class object to function describe?
I had be grateful if someone could explain me the working of this code.

The function print in class Base is a const member function, hence after inheritance, when we try to override the definition of print in Derived class, why doesn't the compiler give an error.
There is no error because the program is well-formed. It is unclear why you bring up the detail that the member function is const. Constness of a member function has no effect on whether the function can be overridden. Did you assume that const means final?
In this program, how we can we pass a derived class object (d) to the function which expects an argument of data Type Base.
Because that class Base is a public base of the Derived class, and thus the derived object is implicitly convertible to the base. The result of the conversion is a copy of the base class sub object. This is colloquially called "slicing".
Even if we could somehow pass the derived class object to the function, why does it print "This is Base class" instead of "This is Derived Class".
Because there is no derived class object inside the function. There is a copy of the base.
Does implicit type-conversion take place when I pass a derived class object to function describe?
Yes. When you pass an argument of a type that is different from the type of a non-reference parameter, there is always an implicit conversion.
Indirection is necessary for runtime polymorphism. Try the same using a reference to base as parameter and you'll see the overriding function called.

Your first question is why it did not give you an error because your function is const. Const function does not prohibit you from overriding it. If you want your function to be not overridden by derived classes you can declare that function final.
virtual string print() const final;
Now this will not be overridable by any other derived class. As far as you are concerned about the const. You can Overload your function on the basis of constness. For example, you can have.
virtual string print() const; // Does not modify anything
virtual string print(); Can modify `this`
For the second question can pass the Derived class object to a function witch expect the Base class object. But It is only possible if it is via reference or via a pointer.
void describe(const Base& p);
void describe(Base* p);
For the third question as you passed via copy, so your derived class object is narrowed to Base class. Which essentially loss all the additional information other than its Base class.
The fourth question has the same answer as 3.
This is fully functional code as you had expected to run.
#include <iostream>
#include<string>
using namespace std;
class Base
{
public:
virtual string print() const
{
return "This is Base class";
}
};
class Derived : public Base
{
public:
virtual string print() const override
{
return "This is Derived class";
}
};
void describe(const Base& p)
{
cout << p.print() << endl;
}
int main()
{
Base b;
Derived d;
describe(b);
describe(d);
return 0;
}
Here you can see I declared overridden function override to tell the compiler that this function is being overridden from its Base Class. Without this, it works as expected but it's like function hiding rather than overriding.

Related

Operator<< in base class not visible in derived class [duplicate]

I am trying to understand why the following code does not compile, apparently the solution relies in specifically declaring the dependency on method_A in the derived class.
Please refer to the following code:
class Base
{
public:
void method_A(int param, int param2)
{
std::cout << "Base call A" << std::endl;
}
};
//does not compile
class Derived : public Base
{
public:
void method_A(int param)
{
std::cout << "Derived call A" << std::endl;
}
};
//compiles
class Derived2 : public Base
{
public:
using Base::method_A; //compile
void method_A(int param)
{
std::cout << "Derived call A" << std::endl;
}
};
int main ()
{
Derived myDerived;
myDerived.method_A(1);
myDerived.method_A(1,2);
Derived2 myDerived2;
myDerived2.method_A(1);
myDerived2.method_A(1,2);
return 0;
}
"test.cpp", (S) The wrong number of arguments have been specified for "Derived::method_A(int)".
What is the technical reason that prevents the derived class to know its base class is implementing the method it's trying to overload?
I am looking in understanding better how the compiler/linker behaves in this case.
Its called Name Hiding. When you define a non virtual method with the same name as Base method it hides the Base class method in Derived class so you are getting the error for
myDerived.method_A(1,2);
To avoid hiding of Base class methods in Derived class use using keyword as you did in Derived2 class.
Also if you want to make it work you can do it explictly
myDerived.Base::method_A(1,2);
Check out this for better explanation why name hiding came into picture.
Well, for one you're calling
myDerived.method_A(1,2);
with 2 arguments, whereas both in base and derived the method is declared to take only one argument.
Secodnly, you're not overriding anything, because method_A is not virtual. You're overloading.
If your intention is to override void Base::method_A(int param, int param2) then you should mark it virtual in the base class:
virtual void method_A(int param, int param2)
Any function overriding this must have the same parameters and almost the same return type ('almost' loosely meaning that the differing return types must be polymorphically related, but in most cases it should have the identical return type).
All you're currently doing is overloading the function in the base class. The using keyword is bringing the base class function into the child class' namespace, as the language behaviour is not to do this by default.

Derived Class Pointer Pointing To Base Class Object Using Static_Cast [duplicate]

This question already has answers here:
Downcasting using the 'static_cast' in C++
(3 answers)
Closed 3 years ago.
I have the below piece of code where I have a base class and a derived class. Both base class and derived class are having a function member sharing the same name. In the main(), I have typecasted a base class object to a derived class pointer and trying to call the function. To my utter surprise, it is calling the derived class function member. As far as I know, the base class object won't be having any information about the derived class object. So, how come my derived class pointer is still able to access the derived member function?
In the case of upcasting, I do understand derived class object will be having the contents of the base class that's why a base class pointer pointing to a derived class object will work as expected.
Can someone please help me in understanding how the derived class member function is getting called in this even when I am having a derived class pointer pointing to a base class object(which is having no information of derived class)?
#include<iostream>
using namespace std;
class base
{
public:
void b()
{
cout << "base";
}
};
class derived:public base
{
public:
void b()
{
cout << "derived";
}
};
int main()
{
base b;
derived * d1;
d1 =static_cast<derived*>(&b);
d1->b();
return 0;
}
In your specific case, it's perfectly normal that b is called.
You have a pointer to Derived class, b it's not virtual. So the compiler will generate a call to Derived::b method.
Now, when b will be executed, as you put crap in the this pointer, it's undefined behavior.
But in your case, as you do not access the this pointer, there's no probleme.
Cast a base class to derived class results undefined behavior
As I know, the function doesn't takes any extra space in memory, it stores like the normal function. You can see a member function as a normal function with an extra this pointer. In general, which function to call is determined by the type of the object pointer. But the virtual function is different, it is called by virtual function table, in your code, there is no virtual function declared. So there is no virtual function table.
You can see your code in a different way:
void derived_b(derived* this)
{
cout << "derived";
}
void base_b(base* this)
{
cout << "base";
}
int main()
{
base b;
derived * d1;
d1 =static_cast<derived*>(&b);
derived_b(d1);
return 0;
}
If you define some member in class, and use it in function b, it may cause some error.like
class base
{
public:
void b()
{
cout << "base";
}
};
class derived:public base
{
int a;
public:
derived(){a = 1;}
void b()
{
cout << "derived" << a;
}
};
your code in main() may cause error because the object b don't have any member in memory.

Is it possible to force non-const virtual methods from superclasses to take precedence over const methods of the same name in a subclass?

Consider the following class definitions:
class foo {
virtual absl::Span<const Input *const> GetInputs() const = 0;
virtual absl::Span<Input *const> GetInputs() {
auto mutable_inputs = GetMutableInputs();
return absl::MakeSpan(mutable_inputs.begin(), mutable_inputs.end());
}
}
class bar : public foo {
absl::Span<const Input *const> GetInputs() const override {
return absl::MakeConstSpan(inputs_);
}
}
When calling bar.GetInputs() it seems like the only implementation found is the the one that returns a span of constant inputs. If I have an instance of bar, and want to create a span of non-const inputs, then I must cast bar to foo, and then call GetInputs.
If I cast bar to foo, then call GetInputs, I am then able to assign the result to a span of non-const inputs. Why does the compiler fail to identify the inherited non-const method with the correct return type? Is there a way to make the subclass identify that method?
In other words, is there a way to make the following code compile:
absl::Span<Input *const> tmp = bar.GetInputs()
If I understand your question, it has nothing to do with virtual functions or "precedence" of const, but is plain old "name hiding".
#include <iostream>
class Base {
public:
virtual void f(int) { std::cout << "Base(int)\n"; }
virtual void f(double) { std::cout << "Base(double)\n"; }
};
class Derived : public Base {
public:
virtual void f(double) { std::cout << "Derived(double)\n"; }
};
int main() {
Derived d;
int x=0;
d.f(x);
}
output: Derived(double)
The issue is, name lookup doesn't work the way it seems you expect.
For a given scope, it searches for names to build an overload set. Within the context of Derived, there is only one f(), so when it's found, the compiler stops searching further for more overloads.
It finds Derived(double) and that's the entire overload set, and so it is selected. When you cast your derived class to a reference to the base, and then call something, both functions (declared in the base) are considered, and overload resolution selects the best match.
Now, normally, for polymorphic types you are working with the objects in terms of pointers/references to the base, so it's not an issue. But if you are calling directly on the derived class (perhaps from inside a member of derived?) then it'll have this issue of the derived declaration hiding the base names.
To make the base names visible in the derived class, it's easy:
class Derived : public Base {
public:
using base::f; // <<<<<<<< just add this
virtual void f(double) { std::cout << "Derived(double)\n"; }
};
you should add
using foo::GetInputs;
in bar class to expose the base class function.
you will be able to call the base class function if the object is non-const

C++: Method overloading when inheritance and "using" are involved

Say there are two classes: Base and Derived. The code is listed below. My question is, how does the program know d.print() (tagged with A in code) is meant to call Derived::print() instead of Base::print()?
Please note that I deliberately added using Base::print; to confuse the compiler. These two print() methods have the same signature (am I right?) and are not hiding each other because of the using statement.
#include <iostream>
using namespace std;
class Base {
public:
void print() { cout << "print() of Base is called\n"; }
};
class Derived : public Base {
public:
void print() { cout << "print() of Derived is called\n"; }
using Base::print; // I delibarately added this line
};
int main() {
Derived d;
d.print(); // A
Base *pBase = (Base *)&d;
pBase->print(); // B
}
The result is
print() of Derived is called
print() of Base is called
Edit: the accepted answer gave a quote. For readers' convenience I paste the (nearly) whole quoted paragraph here, split in sentence:
Using-declaration introduces a member of a base class into the derived class definition, such as to expose a protected member of base as public member of derived.. (that's what I expected)
If the name is the name of an overloaded member function of the base class, all base class member functions with that name are introduced. (that's what I expected, too)
If the derived class already has a member with the same name, parameter list, and qualifications, the derived class member hides or overrides (doesn't conflict with) the member that is introduced from the base class. (solved my problem)
The explicitly introduced using does not hide the method you have in the derived class because of this rule (from the cppreference documentation for using)
If the derived class already has a member with the same name, parameter list, and qualifications, the derived class member hides or overrides (doesn't conflict with) the member that is introduced from the base class.
The compiler is not confused, it's doing the right thing. The using is not hiding the print() method in the derived class because it defines a print() method.
When you call print() with a Base pointer, print() is not virtual the base pointer can only call the method that is registered with the static type of the thing it is pointing to, i.e. Base::print()

overloading base class method in derived class

I am trying to understand why the following code does not compile, apparently the solution relies in specifically declaring the dependency on method_A in the derived class.
Please refer to the following code:
class Base
{
public:
void method_A(int param, int param2)
{
std::cout << "Base call A" << std::endl;
}
};
//does not compile
class Derived : public Base
{
public:
void method_A(int param)
{
std::cout << "Derived call A" << std::endl;
}
};
//compiles
class Derived2 : public Base
{
public:
using Base::method_A; //compile
void method_A(int param)
{
std::cout << "Derived call A" << std::endl;
}
};
int main ()
{
Derived myDerived;
myDerived.method_A(1);
myDerived.method_A(1,2);
Derived2 myDerived2;
myDerived2.method_A(1);
myDerived2.method_A(1,2);
return 0;
}
"test.cpp", (S) The wrong number of arguments have been specified for "Derived::method_A(int)".
What is the technical reason that prevents the derived class to know its base class is implementing the method it's trying to overload?
I am looking in understanding better how the compiler/linker behaves in this case.
Its called Name Hiding. When you define a non virtual method with the same name as Base method it hides the Base class method in Derived class so you are getting the error for
myDerived.method_A(1,2);
To avoid hiding of Base class methods in Derived class use using keyword as you did in Derived2 class.
Also if you want to make it work you can do it explictly
myDerived.Base::method_A(1,2);
Check out this for better explanation why name hiding came into picture.
Well, for one you're calling
myDerived.method_A(1,2);
with 2 arguments, whereas both in base and derived the method is declared to take only one argument.
Secodnly, you're not overriding anything, because method_A is not virtual. You're overloading.
If your intention is to override void Base::method_A(int param, int param2) then you should mark it virtual in the base class:
virtual void method_A(int param, int param2)
Any function overriding this must have the same parameters and almost the same return type ('almost' loosely meaning that the differing return types must be polymorphically related, but in most cases it should have the identical return type).
All you're currently doing is overloading the function in the base class. The using keyword is bringing the base class function into the child class' namespace, as the language behaviour is not to do this by default.