C++ overloading and overriding - c++

This code generates the following compilation error :
error: no matching function for call to 'C::print(int)'
can you help me figuring out the procedure that the compiler did to generate that error , (why it ignored the function in class B)
#include <iostream>
using std::cout;
class A {
public:
virtual void print ()
{ cout << "A";}
};
class B : public A {
int x;
virtual void print (int y)
{cout << x+y;}
};
class C : public B {
public:
void print ()
{cout << "C";}
};
int main () {
C* ptr = new C;
ptr->print (5);
}

Each subsequent definition of print hides its parent's. You need a using statement to unhide it:
class A {
public:
virtual void print ()
{ cout << "A";}
};
class B : public A {
public:
int x=1;
using A::print;
virtual void print (int y)
{cout << x+y;}
};
class C : public B {
public:
using B::print;
void print ()
{cout << "C";}
};
Demo
Your pointer is to C*, not B*. You wouldn't technically need to 'unhide' any print functions if your code looked like this:
B* ptr = new C;
However that this sort of hiding is not a particularly good idea... you should prefer overriding and just naming functions different things.

The compiler resolves overloads for the closest (class) type seen. So class C effectively hides the function signature inherited from class B.
To call for that specific function you have to qualify its scope explicitely:
ptr->B::print (5);
// ^^^

overloading means two things(eg functions) have same name in same space or scope like in same class but in overriding we rewrite the definition of function in different scope(class) but the name still remains same.

Related

Why is only derived class member function called?

In the following code:
Please tell me why only derived class member function is called, is it because of hiding? And why an error doesn't occur in b.func(1.1);, the parameter is int x.
#include <bits/stdc++.h>
using namespace std;
class A {
public:
virtual int func(float x)
{
cout << "A";
}
};
class B : public A {
public:
virtual int func(int x)
{
cout << "B";
}
};
int main()
{
B b;
b.func(1); // B
b.func(1.1); // B
return 0;
}
Yes it's because of hiding. This is one of the main reasons you should always add the special identifier override on functions you intend to override:
class B : public A {
public:
virtual int func(int x) override // <- Note the override here
{
cout << "B";
}
};
This will cause the compiler to complain about not actually overriding.
And floating point values can be implicitly converted to integers.

Why GCC/Clang don't resolve an overriden method with the same name? [duplicate]

In the example below I have a abstract class with pure virtual method (aka FUN1) and a normal method (aka FUN2).
#include <iostream>
class A
{
public:
virtual void fun(int i) = 0; // FUN1
void fun() { this->fun(123); } // FUN2
};
class B : public A
{
public:
virtual void fun(int i) { std::cerr << i << std::endl; }
};
int main(int,char**)
{
B b;
b.fun();
}
Why can't I call FUN2 on derived class? g++ gives an error:
main.cpp:19:8: error: no matching function for call to ‘B::fun()’
EDIT: note that Overload of pure virtual function question is different. I don't want to override methods.
This is how derived class member lookup works: in the expression b.fun(), fun is first looked up in the scope of class B, and the lookup finds B::fun(int). So it stops and never finds A::fun().
Relevant section of the standard is 10.2 [class.member.lookup]/4:
If C contains a declaration of the name f, the declaration set contains every declaration of f declared in
C that satisfies the requirements of the language construct in which the lookup occurs. (...) If the resulting declaration set is not empty, the subobject set contains C itself, and calculation is complete.
To make the base class function directly accessible you can use a using declaration in the derived class, i.e. using A::fun;.
For methods that are implemented in the base class an alternative is sometimes to qualify to call, i.e. b.A::fun().
Try to add using A::fun; statement in B class :
#include <iostream>
class A
{
public:
virtual void fun(int i) = 0; // FUN1
void fun() { this->fun(123); } // FUN2
};
class B : public A
{
public:
using A::fun;
virtual void fun(int i) { std::cerr << i << std::endl; }
};
int main(int, char**)
{
B b;
b.fun();
b.fun(5);
}

Can I overload pure virtual method in the base class?

In the example below I have a abstract class with pure virtual method (aka FUN1) and a normal method (aka FUN2).
#include <iostream>
class A
{
public:
virtual void fun(int i) = 0; // FUN1
void fun() { this->fun(123); } // FUN2
};
class B : public A
{
public:
virtual void fun(int i) { std::cerr << i << std::endl; }
};
int main(int,char**)
{
B b;
b.fun();
}
Why can't I call FUN2 on derived class? g++ gives an error:
main.cpp:19:8: error: no matching function for call to ‘B::fun()’
EDIT: note that Overload of pure virtual function question is different. I don't want to override methods.
This is how derived class member lookup works: in the expression b.fun(), fun is first looked up in the scope of class B, and the lookup finds B::fun(int). So it stops and never finds A::fun().
Relevant section of the standard is 10.2 [class.member.lookup]/4:
If C contains a declaration of the name f, the declaration set contains every declaration of f declared in
C that satisfies the requirements of the language construct in which the lookup occurs. (...) If the resulting declaration set is not empty, the subobject set contains C itself, and calculation is complete.
To make the base class function directly accessible you can use a using declaration in the derived class, i.e. using A::fun;.
For methods that are implemented in the base class an alternative is sometimes to qualify to call, i.e. b.A::fun().
Try to add using A::fun; statement in B class :
#include <iostream>
class A
{
public:
virtual void fun(int i) = 0; // FUN1
void fun() { this->fun(123); } // FUN2
};
class B : public A
{
public:
using A::fun;
virtual void fun(int i) { std::cerr << i << std::endl; }
};
int main(int, char**)
{
B b;
b.fun();
b.fun(5);
}

Override pointer-to-member-function

I have these two classes:
class A {
public:
A() { m_ptr = NULL; }
void (*m_ptr)();
void a() { if (m_ptr) m_ptr(); }
};
class B : public A {
public:
B() { m_ptr = b; }
void b() {
std::cout << "B::b() is called" << std::endl;
}
};
And I want to use them like this:
B b;
b.a();
and get the following to be called B::b().
Of course this is not being compiled as B::b is not of type void(*)().
How can I make it work?
UPDATE. To whom who asks "why?" and "what for?".
The class A is a very basic class which has many successors in production code. The class B is 6-th successor and I want to extend A (the most convinient place) to call there one more method (from B) which can be present and may be not in another successors af A and B.
A virtual method with empty body can be employed for that but it is ugly and I want to avoid it. Abstract method even more so (because of existing derived successors code).
I don't want to use external function of type void (*)() to not loose access to internal data of all hierarchy.
You can't make it work as your classes are defined now.
Calling a non-static member function of another class requires an instance of that class. You either need to store a reference to the object that owns the member function when storing the function pointer, or pass a reference to the object when you make the call to A::a.
You also need to declare m_ptr with the type void (B::*)(), which is pointer to member of B that is a function taking no parameters and returning void.
Look at this example:
class A {
public:
A() { m_ptr = nullptr; }
void a(B& b) { if (m_ptr) (b.*m_ptr)(); } // Now takes reference to B object.
void (B::*m_ptr)(); // Pointer to member function of B.
};
class B : public A {
public:
B() { m_ptr = &B::b; } // Adress of qualified function.
void b() {
std::cout << "B::b() is called" << std::endl;
}
};
Now we can call B::b like this:
B b;
b.a(b); // Pass reference to b when calling.
Your use of inheritence in this way is confusing as it implies that the real problem you are trying to solve is to invoka a member of a derived class through the base class. This is usually accomplished using a simple virtual function like this:
class A {
public:
virtual ~A() {}
void a() const { b(); } // Call b.
private:
virtual void b() const {}
};
class B : public A {
public:
virtual void b() const override { // C++11 override specifier (optional).
std::cout << "B::b() is called" << std::endl;
}
};
And used like this:
B b;
b.a(); // B::b is called.
Well, probably not the purpose of this exercise, but you can simply declare static void b() if you want to make it work.
Another option is to declare friend void b(), but then the "B::b() is called" printout would be stating a wrong fact.
I would suggest using CRTP since you want to avoid virtual mechanism. Note, however, your code might require some design changes to accommodate this pattern. But it does provide type safety and has no run-time overhead. Hope it helps.
Code on ideone.com:
#include <iostream>
#include <type_traits>
namespace so {
class B;
template<typename T>
class A {
public:
template<typename U = T, typename = typename std::enable_if<std::is_same<U, B>::value>::type>
void foo_A() {
std::cout << "foo_A : ";
static_cast<U *>(this)->foo_B();
}
};
class B: public A<B> {
public:
void foo_B() {
std::cout << "foo_B" << std::endl;
}
};
class C: public A<C> {
public:
void foo_C() {
std::cout << "foo_C" << std::endl;
}
};
} // namespace so
int main() {
so::B b_;
so::C c_;
b_.foo_A();
b_.foo_B();
//c_.foo_A(); Compile error: A<C>::foo_A() does not exist!
c_.foo_C();
return (0);
}
Program output:
foo_A : foo_B
foo_B
foo_C

Overload method/operator with inheritance won't work

I wrote code when one class has only constant access to its content, and that was inherited by other class which provides the same method, but with normal access to its members. When I try to compile it by gcc I get following error code:
error: passing ‘const A’ as ‘this’ argument of ‘void A::operator()()’ discards qualifiers
here is sample compilable code:
#include<stdio.h>
class ConstA {
public:
void operator()() const {
printf("const\n");
}
};
class A : public ConstA {
public:
void operator()() {
printf("non-const\n");
}
};
class B : public A {
};
void f(const A& a) {
a();
}
int main() {
B b;
f(b);
}
Compiler tries to invoke method(operator ()) without const attribute, while const method is accessible in base ConstA class. I do not know why I get this kind of error.
The const method is not accessible, the base class version is hidden by the derived class version, an annoying problem. You need using ConstA::operator() to bring it into the scope of A.
class A : public ConstA{
public:
using ConstA::operator();
void operator()(){
printf("non-const\n");
}
};
For further reading, look at this question of mine, which has some good explanations.
it is because C++ uses hiding on overloading, so after overloading, ConstA::operator() is NOT accessable
consider the following program:
class A {
public:
void foo() { cout << "A" << endl; }
};
class B : public A {
public:
void foo(int x) { cout << "B" << endl; }
};
int main() {
B b;
b.foo();
}
this one will also generate a compile error, because B::foo() is hidden! to envoke it you'll have to explicitly cast to A.
so in your example, you'll have to explicitly cast to ConstA