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
Related
recently i came to know this - if a derived class redefines base class member method(s) then all the base class methods with same name become hidden in derived class.
#include<iostream>
using namespace std;
class Base
{
public:
int fun()
{
cout<<"Base::fun() called";
}
int fun(int i)
{
cout<<"Base::fun(int i) called";
}
};
class Derived: public Base
{
public:
int fun()
{
cout<<"Derived::fun() called";
}
};
int main()
{
Derived d;
d.fun(5); // Compiler Error
return 0;
}
Error :
In function 'int main()':
Line 30: error: no matching function for call to 'Derived::fun(int)'
compilation terminated due to -Wfatal-errors.
but just wanna know the reason behind it? why is it not calling fun(int i) method of Base Class since Derived class is derived from Base
The fundamental reason is to make code more robust.
struct Base {
};
struct Derived : Base {
void f(long);
void g() { f(3); } // calls Derived::f
}
Now suppose Base is defined in a library, and you get an update to that library and the update changes the definition of Base:
struct Base {
void f(int);
};
Now suppose that searches for overloaded functions didn't stop when a name was found. In that case, Derived::g would call Base::f instead of Derived::f, and your derived class would quietly do something completely different from what it did before, and different from what it was designed and documented to do.
You've already discovered that derived-class overloads will shadow (prevent the visibility of) base-class methods by the same name but different parameters. Let's just claim this was done for some historical or perceived safety reason, and look at a fix:
class Derived: public Base
{
public:
using Base::fun; // expose the base-class method
int fun()
{
cout<<"Derived::fun() called";
}
};
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);
};
recently i came to know this - if a derived class redefines base class member method(s) then all the base class methods with same name become hidden in derived class.
#include<iostream>
using namespace std;
class Base
{
public:
int fun()
{
cout<<"Base::fun() called";
}
int fun(int i)
{
cout<<"Base::fun(int i) called";
}
};
class Derived: public Base
{
public:
int fun()
{
cout<<"Derived::fun() called";
}
};
int main()
{
Derived d;
d.fun(5); // Compiler Error
return 0;
}
Error :
In function 'int main()':
Line 30: error: no matching function for call to 'Derived::fun(int)'
compilation terminated due to -Wfatal-errors.
but just wanna know the reason behind it? why is it not calling fun(int i) method of Base Class since Derived class is derived from Base
The fundamental reason is to make code more robust.
struct Base {
};
struct Derived : Base {
void f(long);
void g() { f(3); } // calls Derived::f
}
Now suppose Base is defined in a library, and you get an update to that library and the update changes the definition of Base:
struct Base {
void f(int);
};
Now suppose that searches for overloaded functions didn't stop when a name was found. In that case, Derived::g would call Base::f instead of Derived::f, and your derived class would quietly do something completely different from what it did before, and different from what it was designed and documented to do.
You've already discovered that derived-class overloads will shadow (prevent the visibility of) base-class methods by the same name but different parameters. Let's just claim this was done for some historical or perceived safety reason, and look at a fix:
class Derived: public Base
{
public:
using Base::fun; // expose the base-class method
int fun()
{
cout<<"Derived::fun() called";
}
};
Please consider the following code :
#include <iostream>
using namespace std;
class superclass;
class subclass;
class subclass2;
class superclass
{
public:
unsigned int a;
superclass **superman;
};
class subclass : public superclass
{
public:
unsigned int b;
};
class subclass2 : public superclass
{
public:
unsigned int b;
};
class runner
{
public:
superclass **superman;
runner()
{
*superman=new superclass[2];
superman[0]=new subclass;
superman[0]->a=3;
superman[1]=new subclass2;
superman[1]->a=4;
}
};
int main() {
runner r;
cout<<r.superman[0]->a<<" "<<r.superman[1]->a;
return 0;
}
As you can see I want to create a dynamicaly alocated storage of references to a parent class each of which can then point to a child class how ever I do not know how to extract the child class out again from that array so i may access its variable b;
I have tried the following approaches but they have not worked for me and give the error
"conversion from 'superclass*' to non-scalar type 'subclass' requested" and
"conversion from 'superclass*' to non-scalar type 'subclass2' requested"
subclass s1=r.superman[0];
subclass2 s2=r.superman[1];
I am sure I am missing something small.
PS: I could not find a similar question, but if it exists, please redirect me,
also i would like a solution that does not require me to use vector or any inbuilt
pre-existing library class.
You really want smart pointer in this case and superclass doesn't need to have a pointer to itself. You can can store superclass pointer in vector which points to real derived class so the polymorphism still works:
#include <memory>
#include <vector>
struct superclass
{
public:
superclass() : a(0) {}
virtual ~superclass() {} // it's important to define virtual destructor as superclass is a base class
int getA() const { return a; }
private:
unsigned int a;
};
class subclass : public superclass
{
public:
unsigned int b;
};
class subclass2 : public superclass
{
public:
unsigned int b;
};
class runner
{
public:
std::vector<std::unique_ptr<superclass>> superman;
runner()
{
superman.emplace_back(new subclass());
superman.emplace_back(new subclass2());
}
};
Then you can access it simply:
int main()
{
runner r;
std::cout << r.superman[0]->getA() <<" " < <r.superman[1]->getA();
return 0;
}
Side note: hide your data if you can, access data through set/get functions, don't declare members as public.
superclass **superman;
runner()
{
*superman=...
These few lines of code give undefined behaviour to the code. You cannot dereference an uninitialised pointer and expect everything to work just fine.
Add a virtual destructor in superclass and use dynamic_cast:
class superclass
{
public:
unsigned int a;
superclass **superman;
virtual ~superclass(){}; // You must at least have one virtual method
// in your superclass and destructor is good choice
// Otherwise, dynamic_cast wouldn't work:
// error: ... (source type is not polymorphic) !
};
// ...
// s1 and s2 must be pointers:
subclass *s1=dynamic_cast<subclass* >(r.superman[0]);
subclass2 *s2=dynamic_cast<subclass2*>(r.superman[1]);
//...
Note: Be careful about casting from base class to a derived class. And don't forget to release allocated memory.
so I got this problem while trying to overload in c++:
I have those classes:
class Data
{
public:
void virtual f(){cout<<"In data!"<<endl;}
};
class A: public Data
{
public:
void f(int x){cout<<"Class A int is: "<<x<<endl;}
};
then I do:
Data *D=new A();
D->f(4);
I expect the Data's f() function to do to class A's f() function since I did it virtual, but it won't.
Any ways to make it work?
That's not the same function, the one in the derived class takes an int parameter.
That shouldn't even compile, because Data doesn't have a method called f(int).
For polymorphism to work, you need the same signature:
class Data
{
public:
void virtual f(int){cout<<"In data!"<<endl;}
// |
// dummy parameter
};
class A: public Data
{
public:
void f(int x){cout<<"Class A int is: "<<x<<endl;}
};
You need to have the same parameters when overloading. Your compiler sees doStuff(int a), doStuff(String a) and doStuff() as different functions. Be sure they all have the same parameters when you're overloading.
Overloading does not work across class boundaries.
Here is something you can do to be able to call both using an object of class A -
class Data
{
public:
void virtual f(){cout<<"In data!"<<endl;}
// |
// dummy parameter
};
class A: public Data
{
using Data::f;
public:
void f(int x){cout<<"Class A int is: "<<x<<endl;}
};