This is a very basic question, but my C++ skills are a bit rusty...
I have a base class that has a member function that takes 3 arguments, e.g.:
class MyBaseClass
{
public:
int func(int a, char b, int c);
};
and a derived class that overloads that function with a 1-argument version., e.g:
class MyDerivedClass : public MyBaseClass
{
public:
int func(float a);
};
When I try to call the function from the base class on an object of the derived class, like this:
MyDerivedClass d;
d.func(1, 'a', 0);
the compiler complains that MyDerivedClass::func() does not take 3 arguments. That is true, but shouldn't I be able to access the base class function through an object of the derived class?
What am I doing wrong?
MyDerivedClass::func is hiding the name MyBaseClass::func. You can fix this with a using declaration:
class MyDerivedClass : public MyBaseClass
{
public:
using MyBaseClass::func;
int func(float a);
};
You probably intended to declare the method MyBaseClass::func() as virtual
But, if you really want to achieve
when I try to call the function from the base class on an object of
the derived class, like this
then, you can try
MyDerivedClass d;
d.MyDerivedClass::func( 3.14f );
This compiles and works, but does not seem to be good design.
the compiler complains that MyDerivedClass::func() does not take 3
arguments
That is indeed true, per your class definition, MyDerivedClass::func() takes only one argument.
Add "using Class::func;" in MyDerivedClass.
class MyDerivedClass : public MyBaseClass
{
public:
using MyBaseClass::func;
int func(float a);
};
Related
Method func from DerivedClass override the method func and all its overloads from BaseClass.
#include <cstdio>
class BaseClass
{
public:
void func(int a){puts("BaseClass::func(int)");};
void func(int a, int b){puts("BaseClass::func(int, int)");};
void func(int a, int b, int c){puts("BaseClass::func(int, int, int)");};
//...
};
class DerivedClass : public BaseClass
{
public:
void func(int a){puts("DerivedClass::func(int)");}
//...
};
int main()
{
DerivedClass obj;
obj.func(0);
obj.func(0, 0); // error
obj.func(0, 0, 0); // error
return 0;
}
How can I fix this code to end up on the screen was derived:
DerivedClass::func(int)
BaseClass::func(int, int)
BaseClass::func(int, int, int)
Edit 1
In functions main should not change anything
The derived class's member function doesn't override the base class ones, it hides them. To bring them all to scope, use a using declaration:
class DerivedClass : public BaseClass
{
public:
void func(int a){puts("DerivedClass::func(int)");}
using BaseClass::func;
//...
};
Live example
It's by design: the phenomenon is called "name hiding".
[Short answer]:
C++ doesn't like the idea that a long-standing behavior as calling one base-function with a specific set of parameters can be modified in one of your subclasses and chose to hide all overloads in every base class to solve this.
[Long answer] here:
https://stackoverflow.com/a/1629074/1938163
As a workaround you can cast the object to the appropriate base and call the functions you need (there's a cast penalty though), or better call the function you need directly by specifying its base class
int main()
{
DerivedClass obj;
obj.func(0);
obj.BaseClass::func(0,0);
return 0;
}
Live Example
or you can un-hide them with a "using directive"
class DerivedClass : public BaseClass
{
public:
void func(int a){puts("DerivedClass::func(int)");}
using BaseClass::func;
//...
};
Live Example
Please provide me with a specific answer why function overriding hides the functions that are overloaded in base class.
class Base{
public:
fun(int,int);
fun(B);
};
class Derived:public Base
{
public:
fun();
};
int main()
{
Derived d;
d.fun(1,2); // error
return 0;
}
TTBOMK this doesn't have a real technical reason, it's just that Stroustrup, when creating the language, considered this to be the better default. (In this it's similar to the rule that rvalues do not implicitly bind to non-const references.)
You can easily work around it be explicitly bringing base class versions into the derived class' scope:
class Base {
public:
void fun(int,int);
void fun(Base);
};
class Derived : public Base {
public:
using Base::fun;
void fun();
};
Also refer WHY link as it tells why base overloaded method is hidden in derived class: WHY
I want to know the below code is correct or not
class A
{
public :
int show (int x, int y);
};
class B : public A
{
public :
float show (int a, int b); // can i overload this function ?
};
the show function is present in both base and derived class with different written types.
I know function overloading concept (can not overload with different return types).
Is this possible to do so?
The code will be compiled successfully. The method A::show will not be overloaded but hidden.
You can call this method with the scope operator.
Check this link or this link
Class A
{
Public :
virtual int show (int x, inty) = 0;
};
class B:Public A
{
Public :
float show (int x, int y);
};
When i declare base obj and point it to derived class :
A aObj;
B bObj;
aObju = &bObj;
bObj.Show(); // Which function will be called base class or derived class?
If you create a derived class object like
1)
B b;
b.show();
OR
2)
A* b = new B();
b->show();
Will always look into derived class, and call B::show().
This is for your particular example, where no virtual functions are present, if virtual functions are present in the base class, the second case can give different results in other cases, but in this particular example even base class virtual functions will make no difference.
What does it mean to have a using inside a class definition?
class myClass {
public:
[...]
using anotherClass::method;
};
That declaration unhides a base class member. This is most often used to allow overloads of a member function. Example:
class Base {
public:
void method() const;
};
class Derived : public Base {
public:
void method(int n) const;
// Without the using, you would get compile errors on d.method();
using Base::method;
};
The case I've seen it:
class A
{
void foo(int);
void foo(float);
}
class B : public A
{
void foo(string);
}
B b;
b.foo(12); // won't work!
Because I have implemented a new foo function in B with a different signature it hides the foo functions from A. In order to override this behavior I would do:
class B : public A
{
void foo(string);
using A::foo;
}
Most often, syntax like this is used like so:
class derived : public base {
public:
[...]
using base::method;
};
The using declaration here unhides a member declaration from the parent class. This is sometimes necessary if another member declaration in derived may hide the member from base.
If anotherClass is a base class that contains a member function like
virtual void f();
and you decide to overload the function in the derived class like
virtual void f(int);
it "hides" f() in the base class. Calling f() through a pointer to the derived class for example, would result in an error, since the compiler does not "see" the version of f() taking no arguments from the base class anymore.
By writing
using Base::f;
you can bring the base classes function back into scope, thus enabling overload resolution as you might have expected it to work in the first place.
It must be something specific in my code, which I can't post. But maybe someone can suggest possible causes.
Basically I have:
class CParent
{
public:
void doIt(int x);
};
class CChild : public CParent
{
public:
void doIt(int x,int y,int z);
};
CChild *pChild = ...
pChild->doIt(123); //FAILS compiler, no method found
CParent *pParent = pChild;
pParent->doIt(123); //works fine
How on earth?
EDIT: people are talking about shadowing/hiding. But the two versions of doIt have different numbers of parameters. Surely that can't confuse the compiler, overloads in child class which can't possibly be confused with the parent class version? Can it?
The compiler error I get is:
error C2660: 'CChild::doIt' : function does not take 1 argument
You have shadowed a method. For example:
struct base
{
void method(int);
void method(float);
};
struct derived : base
{
void method(int);
// base::method(int) is not visible.
// base::method(float) is not visible.
};
You can fix this with a using directive:
class derived : public base
{
using base::method; // bring all of them in.
void method(int);
// base::method(int) is not visible.
// base::method(float) is visible.
};
Since you seem insistent about the number of parameters, I'll address that. That doesn't change anything. Observe:
struct base
{
void method(int){}
};
struct derived : base
{
void method(int,int){}
// method(int) is not visible.
};
struct derived_fixed : base
{
using base::method;
void method(int,int){}
};
int main(void)
{
{
derived d;
d.method(1, 2); // will compile
d.method(3); // will NOT compile
}
{
derived_fixed d;
d.method(1, 2); // will compile
d.method(3); // will compile
}
}
It will still be shadowed regardless of parameters or return types; it's simply the name that shadows. using base::<x>; will bring all of base's "<x>" methods into visibility.
You are hitting a classic problem. You need using CParent::doIt; in your CChild class. I'll scrounge up the duplicate questions.
Edit:
Here's my answer to essentially the same question: Overriding a Base's Overloaded Function in C++
I have never done this without having that method in the base class before. I think that adding "using CLASS::METHOD" in derived class will give you access to the other version of the overloaded method.
class CParent
{
public:
void doIt(int x);
};
class CChild : public CParent
{
public:
void doIt(int x,int y,int z);
using CParent::doIt;
};
The problem is CChild doesn't actually inherit from CParent.
And so it doesn't have a doIt method that takes only one argument.
When you override a function in the derived class, only that function in the derived class is visible to the user of that class. The base class version becomes hidden.
Therefore, your pChild pointer calling doIt(int x) will fail since you are using a derived class pointer to call the base class function. The pParent pointer calling doIt(int x) will work since you are using a base class pointer to call the base class function. Even though you have a child object being pointed to by a parent pointer (upcasted), the class type here is determined by the declaration of the pointer which is a CParent.
To be able to call that base class function using the derived class pointer, you can:
Qualify the base class name in the function call, as in the following:
pChild->CParent::doIt(123);
Use a using directive to bring the function name from the base class into the derived class, as seen in the previous posts.
I understand that this behavior is to give you flexibility to override the behavior of base class method in your derived class.
Lets assume that you have a function foo(int) in base class and you want to change the behavior of this function in your derived class. Now if the base class method is not hidden by your derived class method (which has same prototype as that of base class's method), it will introduce ambiguity in overload resolution.
The method in your child class has a different number of arguments than what you're trying to pass into it. Could it be related to that?