Redifinition of functions in derived class - c++

In C++ primer plus it is written that
"If you redefine just one version of function in derived class, the other functions of base class become hidden and cannot be used by objects of the derived class."
Then why does this code call fun1() ,as it should be hidden for the derived class object i.e. obj.
#include<iostream>
using namespace std;
class base
{
public:
void fun1()
{
cout<<"base"<<endl;
}
void fun2(int a)
{
cout<<"function2";
}
};
class derived :public base
{
public:
void fun2()
{
cout<<"fun2";
}
};
int main()
{
derived obj;
obj.fun1();
}

When it says "the other functions of the base class become hidden" it actually means "the base class functions with the same name become hidden in the derived class".
So, if you declare two overloaded versions of fun1 in the base class (say, fun1(void) and fun1(int)), and then declare another version of fun1 in the derived class (say, fun1(double)), the function in the derived class will hide both fun1 functions inherited from the base class.
In your example, the derived fun2 hides the base fun2, but it doesn't hide base fun1. This is why you can successfully call fun1 in your example.
You can observe the fact that derived fun2 has hidden the base fun2 by trying to call
obj.fun2(42);
Since the fun2(int) from the base class is hidden by fun2(void) from the derived class, the call will fail to compile.

In the above example you have not redefined fun1, but redefined fun2. so if you call fun1 it would still call the base class function. but if you call obj.fun2() it will class derived class function.

You haven't redefined any version of fun1; you have only overloaded fun2. This doesn't hide everything in the base class; it hides the other overloads of the same function.

if you want a function in a derived class do something different to the parent class then you need to make the parent function virtual.
virtual void fun1() { ... }

Related

C++: Method overloading when inheritance and "using" are involved

Say there are two classes: Base and Derived. The code is listed below. My question is, how does the program know d.print() (tagged with A in code) is meant to call Derived::print() instead of Base::print()?
Please note that I deliberately added using Base::print; to confuse the compiler. These two print() methods have the same signature (am I right?) and are not hiding each other because of the using statement.
#include <iostream>
using namespace std;
class Base {
public:
void print() { cout << "print() of Base is called\n"; }
};
class Derived : public Base {
public:
void print() { cout << "print() of Derived is called\n"; }
using Base::print; // I delibarately added this line
};
int main() {
Derived d;
d.print(); // A
Base *pBase = (Base *)&d;
pBase->print(); // B
}
The result is
print() of Derived is called
print() of Base is called
Edit: the accepted answer gave a quote. For readers' convenience I paste the (nearly) whole quoted paragraph here, split in sentence:
Using-declaration introduces a member of a base class into the derived class definition, such as to expose a protected member of base as public member of derived.. (that's what I expected)
If the name is the name of an overloaded member function of the base class, all base class member functions with that name are introduced. (that's what I expected, too)
If the derived class already has a member with the same name, parameter list, and qualifications, the derived class member hides or overrides (doesn't conflict with) the member that is introduced from the base class. (solved my problem)
The explicitly introduced using does not hide the method you have in the derived class because of this rule (from the cppreference documentation for using)
If the derived class already has a member with the same name, parameter list, and qualifications, the derived class member hides or overrides (doesn't conflict with) the member that is introduced from the base class.
The compiler is not confused, it's doing the right thing. The using is not hiding the print() method in the derived class because it defines a print() method.
When you call print() with a Base pointer, print() is not virtual the base pointer can only call the method that is registered with the static type of the thing it is pointing to, i.e. Base::print()

C++ virtual function behavior

I am doing some exercise on my understanding. on compiling below code I get Derived::disp() called and which in turn calls non-virtual function "Print".
My question is why Derived class "Print"version is called instead of Base print version even "Print" is not virtual.
class Base
{
public:
void print(){
cout<<"Base::Print()\n";
}
virtual void disp(){
cout<<"Base::Disp()\n";
}
};
class Derived: public Base
{
public:
void print(){
cout<<"Derived::Print()\n";
}
void disp(){
cout<<"Derived::Disp()\n";
print();
}
};
void main()
{
Base *pB = new Derived();
pB->disp();
}
output:
Derived::Disp()
Derived::Print()
If you have a call to a NON-virtual function inside a (virtual or non-virtual) member function, the member function of that class is called.
If you were to call pB->print() in main, it would call Base::Print. But as it stands, the pB->Disp() calls Derived::Disp() which calls Derived::Print on the basis that it is called from inside the Derived class.
Within the body of a non-static member function the keyword this has the type of pointer to the object of the class type for which the function is called.
If a virtual function is called for a derived class then this has the type of the pointer of this class.
Inside member functions access to class members looks for example in the context of your program like
( *this ).print();
where this has type Derived *.
Thus member function print of this class is called.

c++ derived functions vs. base functions

Is there a way you can invoke a member function of a base class upon a class derived from it?
Class Bass{
public:
void func();
};
Class Derived: public Base{
public:
void func();
};
I have a practice midterm, and I suspect no, because how would the Base class know about the Derived, but I am not sure.
Is there a way you can invoke a member function of a base class upon a class derived from it?
Not sure exactly what you mean by this, but given your Base and Derived classes you can do the following. Just make sure you use a reference or pointer, not pass-by-value because of the slicing problem.
Call Base::func() from within Derived::func():
void Derived::func()
{
Base::func();
}
Call Base::func() explicitly on a Derived object:
Derived d;
d.Base::func();
I [...] am wondering if you could do something like Base::func(Derived d)
As others have pointed out, you can do this using a forward declaration:
// Tell the compiler "Derived" is a class name.
class Derived;
class Base
{
// Can use the class name since it has been declared.
void func(Derived& derived);
};
// Define the class named "Derived".
class Derived : public Base
{
// ...
};
// Use the derived class.
void Base::func(Derived& derived)
{
// For this bit to work, the definition of `Derived` must
// be visible at this point (like putting the class above
// or including your "Derived.h" from "Base.cpp").
derived.some_derived_method();
}
However, you won't be able to define the Base::func(Derived&) directly in the class definition since you need to finished defining Base and to define Derived first.
if I understand correctly, you need to call base function with derived parameter?
You can do it only using forward declaration and passing derived object by pointer or ref.
class Derived;
class Base{
public:
void func(Derived&);
};
You should be able to do something like this:
class Derived;
class Base {
public:
void func();
void func(Derived);
};
class Derived : public Base {
public:
void func();
};
void
Base::func(Derived D) {
}
It is okay to use incomplete types in the Base's member function declarations, but you must provide the complete type before their definition.
You can use forward declaration of Derived class:
class Derived;
First of all, do you mean methods on an object, or static class methods?
Secondly, the answer is: it depends what the object you're invoking the method call on is. This is the nature of polymorphism: if your object is of type 'Derived', then even if it has been cast to a 'Base' the method call will still invoke the Derived version of func.
Is that what you were asking?

why I changed parent virtual function arguments in child hides the father function c++?

I made a class with virtual function f() then in the derived class I rewrote it like the following f(int) why can't I access the base class function throw the child instance ?
class B{
public:
B(){cout<<"B const, ";}
virtual void vf2(){cout<<"b.Vf2, ";}
};
class C:public B{
public:
C(){cout<<"C const, ";}
void vf2(int){cout<<"c.Vf2, ";}
};
int main()
{
C c;
c.vf2();//error should be vf2(2)
}
You have to do using B::vf2 so that the function is considered during name lookup. Otherwise as soon as the compiler finds a function name that matches while traversing the inheritance tree from child -> parent -> grand parent etc etc., the traversal stops.
class C:public B{
public:
using B::vf2;
C(){cout<<"C const, ";}
void vf2(int){cout<<"c.Vf2, ";}
};
You are encountering name hiding. Here is an explanation of why it happens ?
In C++, a derived class hides any base class member of the same name. You can still access the base class member by explicitly qualifying it though:
int main()
{
C c;
c.B::vf2();
}
You were caught by name hiding.
Name hiding creeps up everywhere in C++:
int a = 0
int main(int argc, char* argv[]) {
std::string a;
for (int i = 0; i != argc; ++i) {
a += argc[i]; // okay, refers to std::string a; not int a;
a += " ";
}
}
And it also appears with Base and Derived classes.
The idea behind name hiding is robustness in the face of changes. If this didn't exist, in this particular case, then consider what would happen to:
class Base {
};
class Derived: public Base {
public:
void foo(int i) {
std::cout << i << "\n";
}
};
int main() {
Derived d;
d.foo(1.0);
}
If I were to add a foo overload to Base that were a better match (ie, taking a double directly):
void Base::foo(double i) {
sleep(i);
}
Now, instead of printing 1, this program would sleep for 1 second!
This would be crazy right ? It would mean that anytime you wish to extend a base class, you need to look at all the derived classes and make sure you don't accidentally steal some method calls from them!!
To be able to extend a base class without ruining the derived classes, name hiding comes into play.
The using directive allows you to import the methods you truly need in your derived class and the rest are safely ignored. This is a white-listing approach.
When you overload a member function in a base class with a version in the derived class the base class function is hidden. That is, you need to either explicitly qualify calls to the base class function or you need a using declaration to make the base class function visible via objects of the derived class:
struct base {
void foo();
void bar();
};
struct derived: base {
void foo(int);
using base::foo;
void bar(int);
};
int main() {
derived().foo(); // OK: using declaration was used
derived().bar(); // ERROR: the base class version is hidden
derived().base::bar(); // OK: ... but can be accessed if explicitly requested
}
The reason this is done is that it was considered confusing and/or dangerous when a member function is declared by a derived function but a potenially better match is selected from a base class (obviously, this only really applies to member functions with the same number of arguments). There is also a pitfall when the base class used to not have a certain member function: you don't want you program to suddenly call a different member function just because a member function is being added to the base class.
The main annoyance with hiding member functions from bases is when there is a set of public virtual functions and you only want to override one of them in a derived class. Although just adding the override doesn't change the interface using a pointer or a reference to the base class, the derived class can possibly not used in a natural way. The conventional work-around for this to have public, non-virtual overload which dispatch to protected virtual functions. The virtual member function in the various facets in the C++ standard library are an example of this technique.

Can you override private functions defined in a base class?

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.