How does compiler implements inheritence? [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++: rationale behind hiding rule
Suppose I have a code:
class A
{
public:
void f(int s) {}
};
class B:public A
{
public:
void f() {}
};
int main()
{ B ob;
ob.f(4);
}
Then in this case compiler generates an error that "no matching function for call to ‘B::f(int)'"
But class B has inherited A as public so B must have the function "void f(int s)". Dont know why compiler is generating error here?

That is because B defines a different f, which hides the f inherited from A. If you want both available in B (which is likely), you must bring it into scope with a using-declaration:
class B : public A
{
void f() {}
using A::f;
};
This behaviour is specified in [class.member.loopkup], especially paragrah 4.

When you declare void f() in B, this hides the void f(int) inherited from A. You can bring it back into scope with using:
class B: public A
{
public:
void f() {}
using A::f;
};

This is called Hiding - you can check the C++ FAQ Entry. It describes the problem and the solution.

Related

Why the parent's method should be called explicitly with the parent's prefix from the child object? [duplicate]

This question already has answers here:
C++ inheritance and name hiding [duplicate]
(3 answers)
Why does an overridden function in the derived class hide other overloads of the base class?
(4 answers)
Closed 5 months ago.
see please the code:
#include <iostream>
using namespace std;
class A{
public:
A() = default;
virtual void foo() = 0;
bool foo(int x)
{
cout<<"A::foo(int x)\n";
return true;
}
bool func(int x)
{
cout<<"A::func(int x)\n";
return true;
}
};
class B: public A
{
public:
B() = default;
void foo()
{
cout<<"B::foo()\n";
}
};
int main()
{
B b;
b.func(0);
//b.foo(0); //it's not compiled
b.A::foo(0);
return 0;
}
It seems the parent's method should be called explicitly with the parent's prefix from the child object for any reason. b.foo(0) is not compiled but if I add A:: prefix like b.A::foo(0) it works.
Why is b.foo(0) not compiled but b.func(0) is?
It is called 'name hiding'.
You have a function called foo without parameters in your subclass. The compiler will hide any other function with the same name from the superclass, unless you declare it with the using A::foo; directive in the child class.
To my knowledge, this is done to avoid confusion of the function calls. All non-overloaded functions will be inherited automatically.
Your code should work, if you write it like this (untested):
class B: public A
{
public:
using A::foo;
B() = default;
void foo()
{
cout<<"B::foo()\n";
}
};
Please note that the using syntax will move ALL functions called foo into your subclass, regardless of their prototype.
For further information, see https://www.ibm.com/docs/en/zos/2.3.0?topic=scope-name-hiding-c-only or https://bastian.rieck.me/blog/posts/2016/name_hiding_cxx/

Inheritance with two functions with different signatures hides the non-virtual function

Forgive the obscure title. It's likely a duplicate but I couldn't find the correct phrase.
Consider the following inheritance hierarchy.
class A
{
public:
virtual void Foo(int i) { printf("A::Foo(int i)\n"); }
void Foo(int a, int b) { Foo(a + b); }
};
class B : public A
{
public:
void Foo(int i) override { printf("B::Foo(int i)\n"); }
};
class C : public B
{
public:
void Bar() { Foo(1, 2); } //error C2660: function does not take two arguments
};
A has two methods named Foo with a different number of parameters. Only one of them is virtual.
B overrides the virtual method.
C tries to call the non-virtual method and encounters an error.
Calling the method as A::Foo(1, 2) does work fine.
Question:
Why can't the compiler deduce that the correct method is found on A?
It seems odd we would have to explicitly add A:: in a call such as:
C c;
c.A::Foo(1, 2);
Because the member function named Foo is found at the class scope of B, and then name lookup stops, so the Foo in class A is not visible, and won't be considered for overload resolution, even if the version in class A is more appropriate. It is name hiding.
You can use using to introduce them into the same scope, and make overload resolution work as you expect. Such as:
class C : public B
{
using A::Foo;
using B::Foo;
public:
void Bar() { Foo(1, 2); }
};
See Unqualified name lookup
LIVE

'class' keyword in function signature - is it standard C++? [duplicate]

This question already has answers here:
Declaring a variable with "class " keyword vs Declaring one without "class" keyword in function signatures
(4 answers)
Closed 8 years ago.
I'm studying code given to me and I see:
AFPSGameMode::AFPSGameMode(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP) { }
I'm specially curious about the use of the class keyword. Is this standard C++ and if so what does it mean?
Thank you.
The class keyword is allowed here, it's just rare to see it placed here since it can either be completely omitted (if this class has been previously declared) or replaced with the forward declaration:
void foo(const class FPostConstructInitializeProperties& p){ ... }
which is equivalent to:
class FPostConstructInitializeProperties; // <-- forward declaration
void foo(const FPostConstructInitializeProperties& p){ ... }
Don't get confused with the weird naming conventions. The snippet you have provided expresses something like this:
class B{
public:
B(){ }
B(const B& b){ };
};
class A{
public:
B my_b;
A(const class B& b) : my_b(b) { } // <-- class keyword in ctor's param decl.
};
that could be used for example like this (but I guess it's clear enough already):
int main() {
B b;
A a(b);
}
As it was old C, if you have struct say,
struct account
{
int field;
..
};
You can use it for creating its variables (objects) like,
account obj;
or,
struct account obj;.
Same is for class, you may use it, or avoid it. But it is usually not used, but permitted.

Best way to call hidden base class method [duplicate]

This question already has answers here:
Why does an overridden function in the derived class hide other overloads of the base class?
(4 answers)
Closed 9 years ago.
In the following code, "d.Foo()" throws a compiler error claiming that function Foo() does not take 0 arguments. Yet a 0-argument function with that name exists in the base class. The line "d.Base::Foo()" is acceptable.
I have a vague memory of learning that the use of a function name in a derived class hides all functions of that name in a base class, even though arguments may be different. I don't remember why, nor do I remember the best way to avoid that problem. Is my solution best, or is there another way to get at Base::Foo()?
Thanks very much!
RobR
// Override.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
class Base
{
public :
void Foo()
{
}
};
class Derived : public Base
{
public:
void Foo(int x)
{
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Derived d;
d.Foo();
d.Base::Foo();
return 0;
}
you can use(!) base class member functions via using
class Derived : public Base {
public:
using Base::Foo;
};
You could define Derived::Foo() as:
class Derived : public Base {
public:
void Foo() { Base::Foo(); }
};

C++ member function virtual override and overload at the same time

If I have a code like this:
struct A {
virtual void f(int) {}
virtual void f(void*) {}
};
struct B : public A {
void f(int) {}
};
struct C : public B {
void f(void*) {}
};
int main() {
C c;
c.f(1);
return 0;
}
I get an error that says that I am trying to do an invalid conversion from int to void*. Why can't compiler figure out that he has to call B::f, since both functions are declared as virtual?
After reading jalf's answer I went and reduced it even further. This one does not work as well. Not very intuitive.
struct A {
virtual void f(int) {}
};
struct B : public A {
void f(void*) {}
};
int main() {
B b;
b.f(1);
return 0;
}
The short answer is "because that's how overload resolution works in C++".
The compiler searches for functions F inside the C class, and if it finds any, it stops the search, and tries to pick a candidate among those. It only looks inside base classes if no matching functions were found in the derived class.
However, you can explicitly introduce the base class functions into the derived class' namespace:
struct C : public B {
void f(void*) {}
using B::f; // Add B's f function to C's namespace, allowing it to participate in overload resolution
};
Or you could do this:
void main()
{
A *a = new C();
a->f(1); //This will call f(int) from B(Polymorphism)
}
Well I think first of all you did not understand what virtual mechanism or polymorhism. When the polymorphism is achieved only by using object pointers. I think you are new to c++. Without using object pointers then there is no meaning of polymorphism or virtual keyword use base class pointer and assign the desired derived class objects to it. Then call and try it.