I have a base class with an implemented function and a pure virtual function which share a name, but not arguments. I can't call the function implemented in the base class from an instance of the derived class.
I've tried adding the function to the derived class instead of the base class and it works, but that would mean I have to add the function to every derived class instead of implementing it once in the base class.
I've also tried changing the functions name and it works. It seems to be due to a collision between the two overloaded functions.
template <typename T>
class Base {
public:
virtual T some_function(int x) = 0;
T some_function() {
// some code
}
}
class Derived final: public Base<int> {
int some_function() {
// some code
}
}
int main() {
Derived var = Derived();
var.some_function(3);// Compilation error
}
The above code does not compile indicating that it doesn't find the function: some_function(int).
The name some_function in Derived hides the name some_function inherited from Base. You have to bring it back into scope with a using declaration:
class Derived final: public Base<int> {
public:
using Base<int>::some_function;
int some_function() {
// some code
}
}
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";
}
};
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";
}
};
I don't understand why the compiler doesn't like this, here is and example of the problem:
class A
{
public:
virtual void Expand() { }
virtual void Expand(bool flag) { }
};
class B : public A
{
public:
virtual void Expand() {
A::Expand(true);
Expand(true);
}
};
When I try to compile this the A::Expand(true); compiles fine, but the non scoped Expand(true); gets this compiler error:
'B::Expand' : function does not take 1 arguments
You don't need virtual methods for that behaviour. Methods in a derived class hide methods with the same name in the base class. So if you have any function named Expand in your derived class (even if it is an override of a virtual method from the base class), none of the base classes methods with the same name are visible, regardless of their signature.
You can make the base classes methods visible with using. For that you would add using A::Expand; to the definition of B:
class B : public A
{
public:
using A::Expand;
virtual void Expand() { Expand(true); }
};
That's because besides overriding the base Expand(), you're also hiding the base Expand(bool).
When you introduce a member function in a derived class with the same name as a method from the base class, all base class methods with that name are hidden in the derived class.
You can fix this by either qualifying (as you have) or with the using directive:
class B : public A
{
public:
using A::Expand;
virtual void Expand() {
A::Expand(true);
Expand(true);
}
};
I believe, a derived class can override only those functions which it inherited from the base class. Is my understanding correct.?
That is if base class has a public member function say, func, then the derived class can override the member function func.
But if the base class has a private member function say, foo, then the derived class cannot override the member function foo.
Am i right?
Edit
I have come up with a code sample after studying the answers given by SO members. I am mentioning the points which i studied as comments in the code. Hope i am right. Thanks
/* Points to ponder:
1. Irrespective of the access specifier, the member functions can be override in base class.
But we cannot directly access the overriden function. It has to be invoked using a public
member function of base class.
2. A base class pointer holding the derived class obj's address can access only those members which
the derived class inherited from the base class. */
#include <iostream>
using namespace std;
class base
{
private:
virtual void do_op()
{
cout << "This is do_op() in base which is pvt\n";
}
public:
void op()
{
do_op();
}
};
class derived: public base
{
public:
void do_op()
{
cout << "This is do_op() in derived class\n";
}
};
int main()
{
base *bptr;
derived d;
bptr = &d;
bptr->op(); /* Invoking the overriden do_op() of derived class through the public
function op() of base class */
//bptr->do_op(); /* Error. bptr trying to access a member function which derived class
did not inherit from base class */
return 0;
}
You can override functions regardless of access specifiers. That's also the heart of the non-virtual interface idiom. The only requirement is of course that they are virtual.
But if the base class has a private member function say, foo, then the derived class cannot override the member function foo.
In Java, you can't. In C++, you can.
You are correct in that to override a function in a derived class, it must inherit it from the base class (in addition, the base class function must be virtual). However you are wrong about your assumption that virtual functions are not inherited. For example, the following works well (and is actually a known idiom for precondition/postcondition checking):
class Base
{
public:
void operate_on(some thing);
private:
virtual void do_operate_on(some thing) = 0;
};
void Base::operate_on(some thing)
{
// check preconditions
do_operate_on(thing);
// check postconditions
}
class Derived: public Base
{
// this overrides Base::do_operate_on
void do_operate_on(some thing);
};
void Derived::do_operate_on(some thing)
{
// do something
}
int main()
{
some thing;
Base* p = new Derived;
// this calls Base::operate_on, which in turn calls the overridden
// Derived::do_operate_on, not Base::do_operate_on (which doesn't have an
// implementation anyway)
p->operate_on(thing);
delete p;
}
A way to see that private methods are really inherited is to look at the error messages generated by the following code:
class Base
{
private:
void private_method_of_B();
};
class Derived:
public Base
{
};
int main()
{
Derived d;
d.private_method_of_B();
d.method_that_does_not_exist();
}
Trying to compile this with g++ leads tot he following error messages:
privatemethodinheritance.cc: In function 'int main()':
privatemethodinheritance.cc:4: error: 'void Base::private_method_of_B()' is private
privatemethodinheritance.cc:15: error: within this context
privatemethodinheritance.cc:16: error: 'class Derived' has no member named 'method_that_does_not_exist'
If class Derived wouldn't inherit that function, the error message would be the same in both cases.
No You can not over ride any function in base class .
My reason for this notion is that if you define the function in derived class that has the same function signiture in base class , the base class function will become hidden for derived class .
For more information about this exciting issue just visit :
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Foverload_member_fn_base_derived.htm
It's also depends on the type of inheritance
class Derived : [public | protected | private] Base { };
In order to override a function inherited from base class, it should be both virtual, and classified as public or protected.
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.