Inheritance and polymorphism in C++ - c++

my question is about inheritance and polymorphism in C++.
class Base
{
public:
virtual void f() { cout << "Base::f()" << endl; }
void f(string s) { cout << "Base::f(string)" << endl; }
};
class Derivate1: public Base
{
public:
void f() { cout << "Derivate1::f()" << endl; }
void f(int i) { cout << "Derivate1::f(int)" <<endl; }
};
class Derivate2: public Base
{
public:
void f() { cout << "Derivate2::f()" << endl; }
void f(char c) { cout << "Derivate2::f(char)" << endl; }
};
int _tmain(int argc, _TCHAR* argv[])
{
//with base pointers
Derivate1 d1;
Derivate2 d2;
Base *b1 = &d1;
Base *b2 = &d2;
b1->f(); //output: Derivate1::f() ok.
b1->f("string"); //output: Base::f(string) ok.
b1->f(1); //error !
b2->f(); //output: Derivate2::f() ok.
b2->f("string"); //output: Base::f(string) ok.
b2->f('c'); //error !
//with direct derivate object
d1.f(); //output: Derivate1::f() ok.
d1.f("string"); //error !
d1.f(1); //output: Derivate1::f(int) ok.
d2.f(); //output: Derivate2::f() ok.
d2.f("string"); //error !
d2.f('c'); //output: Derivate2::f(char) ok.
return 0;
}
If i want to use a redefined function in base class which is accessible in derived object, what i have to do? I don't want to use Base::f; in derived classes.

In this case you need to tell C++ that you want to include the base class definition of f in the derived class. This is done with a using statement
class Derivate1: public Base
{
public:
using Base::f;
...
};
class Derivate2: public Base
{
public:
using Base::f;
...
};
This essentially tells the C++ compiler to include both the derived class and parent class definitions of f when doing name lookup. Without this the C++ compiler will essentially stop at the first type in the hierarchy which has a member named f and consider only the overloads declared in that type.

C++ is usually very strict on this type of inheritance, if you'd like a work around you could use this to solve issues like this d1.f(); :
static_cast<Base*>(&d1)->f("string");
if you'd like to make calls like this: b1->f(1); well.. you can't. That's the whole point of polymorphism. You'd have to declare a virtual method in the Base class that has a method named f(int i) so that the compiler can link the Base class method and the Derivate1 class method:
class Base
{
public:
//...
virtual void f(int i) { printf("Base::f(int)"); }
};

Related

C++ virtual function: Base class function is called instead of derived

I have following code snippet:
class base
{
public:
virtual void print(char a){ std::cout << " Base\n"; }
};
class derived : public base
{
public:
void print(float a) { std::cout << " Derived\n"; }
};
int main() {
base* d = new derived;
d->print(1.5);
}
Output is Base.
Why is the output coming from the base function and not from the derived one?
You have not overridden the function in the base class, you have overloaded it: The version in the derived class takes a float as an argument, and is quite a different beast from the base class method which takes a char. Moreover, the float version in the derived class shadows the base class version: The base class version becomes inaccessible for calls on the derived type.
As such, the following code
Derived d;
d.print('a');
d.print(1.5);
will print
Derived
Derived
because the call is resolved by the compiler to the only version of print() that's available in Derived.
Likewise, when you call d->print(1.5) through a pointer to Base, the derived class' version is inaccessible to the call: The compiler looks at the base class, sees that there is no print() method defined with a float argument, and converts the argument to char instead. It then calls the only implementation of print(char), which happens to be supplied by the base class.
If you simply change the signature of the print() method in the derived class to match that of the base class, the odd behavior will go away.
When you declare Base* d = new Derived;, the type of the class is Base, as printed by typeid(d).name(), so this instance doesn't have access to child class methods. If you change the type to Derived, you'll call the child method:
#include <iostream>
#include <typeinfo>
class Base
{
public:
virtual void print(char a) {
std::cout << " Base " << std::endl;
}
};
class Derived : public Base
{
public:
void print(float a) {
std::cout << " Derived " << std::endl;
}
};
int main()
{
Derived* d = new Derived;
std::cout << "class type is: " << typeid(d).name() << std::endl;
d->print(1.5);
return 0;
}
Output:
class type is: P7Derived
Derived
Furthermore, declaring the parent class print method virtual doesn't allow an instance of Base to call the child version of print because the child hasn't overridden it (different headers). Creating an instance of Base with Base *d = new Derived; and changing the Derived print method header to void print(char a) in the Derived class would allow you to call the child print method and output Derived, even from an instance of Base, using the virtual keyword.
#include <iostream>
#include <typeinfo>
class Base
{
public:
virtual void print(char a) {
std::cout << " Base " << std::endl;
}
};
class Derived : public Base
{
public:
void print(char a) {
std::cout << " Derived " << std::endl;
}
};
int main()
{
Base* d = new Derived;
std::cout << "class type is: " << typeid(d).name() << std::endl;
d->print(1.5);
return 0;
}
Output:
class type is: P4Base
Derived

C++ inheritance and virtual functions

Reading through a text book, I have come away with the impression that overriding virtual functions only works when using a pointer or reference to the object. The book demonstrates the creation of a pointer of the base class type pointed to an object the derived class type, and uses that to demonstrate a virtual function override.
However, I've now come across the following. Not a pointer in sight, and I was expecting that making function1 virtual would not make a difference, but it does. I'm clearly missing something here and would appreciate an explanation as to what it is. Sorry if my explanation isn't clear; also I expect this has been asked before, but was unable to come up with what to search on.
using namespace std;
class ClassA
{
public:
void function1(); // virtual or not?
void function2();
};
class ClassB : public ClassA
{
public:
void function1();
};
int main()
{
ClassA objA;
ClassB objB;
objA.function1();
cout << "\n";
objA.function2();
cout << "\n";
objB.function1();
cout << "\n";
objB.function2(); // Fourth call
cout << "\n";
}
void ClassA::function1() { cout << "ClassA::function1\n"; }
void ClassA::function2()
{
cout << "ClassA::function2\n";
function1(); // For the fourth call ClassA::function1()
// is called if ClassA::function1() is not virtual
// but ClassB:function1() is called if it is. Why?
}
void ClassB::function1() { cout << "ClassB::function1\n"; }
Many thanks for any help.
It's not a virtual function as it is not marked as one. It's simply a public function accessible from a derived class / object. Your code is not exhibiting polymorphic behavior either. That being said none of your functions are virtual nor overriding. Trivial example for polymorphic installation would be:
#include <iostream>
#include <memory>
class ClassA {
public:
virtual void function1() { // now virtual
std::cout << "ClassA::function1\n";
}
};
class ClassB : public ClassA {
public:
void function1() override {
std::cout << "ClassB::function1\n";
}
};
int main() {
std::unique_ptr<ClassA> p = std::make_unique<ClassB>();
p->function1(); // now calls class B function, overrides class A behavior
}
or through references:
int main() {
ClassB objB;
ClassA& ro = objB;
ro.function1(); // now calls class B function, overrides class A behavior
}
There is little benefit in marking functions as virtual and override if you are not utilizing polymorphic behaviour.
Example of virtual without explicit pointers :
class A
{
public:
virtual void f1()
{
cout << "A::f1()" << endl;
}
void f2()
{
f1();
}
};
class B : public A
{
public:
void f1() override
{
cout << "B::f1()" << endl;
}
};
int main()
{
A a;
B b;
a.f2();
b.f2();
}
function1 is not virtual, obj2 calls the classB function1 because it is a clasB object, the compiler first looks at the most-derived type for a function, then the leftmost base (and on through the bases of that base), and then the next base in multiple inheritance situations. If you took a classA * to obj2 and called function1 it would call the classA function1.

I get the error: cannot declare variable ‘a’ to be of abstract type ‘A’

Here is my code:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void Sub1() = 0;
virtual void Sub2();
virtual void Sub3();
void Sub4();
};
class A : public Base
{
public:
void Sub2();
void Sub4();
};
class B : public A
{
public:
virtual void Sub1();
void Sub2();
};
class C : public Base
{
public:
virtual void Sub1();
virtual void Sub4();
};
void Base::Sub2()
{
cout << "Hello from Base::Sub2()" << endl;
}
void Base::Sub3()
{
cout << "Hello from Base::Sub3()" << endl;
Sub1(); // DONT MISS THIS CALL IN YOUR ANSWER
}
void Base::Sub4()
{
cout << "Hello from Base::Sub4()" << endl;
}
void A::Sub2()
{
cout << "Hello from A:Sub2()" << endl;
}
void A::Sub4()
{
cout << "Hello from A:Sub4()" << endl;
}
void B::Sub1()
{
cout << "Hello from B:Sub1()" << endl;
}
void B::Sub2()
{
cout << "Hello from B:Sub2()" << endl;
}
void C::Sub1()
{
cout << "Hello from C:Sub1()" << endl;
}
void C::Sub4()
{
cout << "Hello from C:Sub4()" << endl; //error used to say from Sub2
}
void Sub(Base& x)
{
x.Sub1();
x.Sub2();
x.Sub3();
}
void AnotherSub(A& a)
{
a.Sub1();
a.Sub2();
a.Sub4();
}
int main()
{
A a; // wont compile
B b;
C c;
Sub(a);
Sub(b);
Sub(c);
AnotherSub(b);
}
I'm having trouble with the A a; and obviously the end Sub(a); because a cannot be used, but at the very end, where it says, "error: cannot declare variable ‘a’ to be of abstract type ‘A’" Any help would be appreciated, Thanks.
--- Also if it helps, the output without the A a; works and looks like:
Hello from B:Sub1()
Hello from B:Sub2()
Hello from Base::Sub3()
Hello from B:Sub1()
Hello from C:Sub1()
Hello from Base::Sub2()
Hello from Base::Sub3()
Hello from C:Sub1()
Hello from B:Sub1()
Hello from B:Sub2()
Hello from A:Sub4()
This line into your class Base:
virtual void Sub1() = 0;
Make the class Base or any class extending it an abstract class if you don't implement the function Sub1, which is the case of your class A.
You cannot create instances of abstract classes, as it has methods with no implementation, which means impossible to call. This kind of classes can only be used through inheritance.
So you need to implement it directly on Base or A if you want to create A instances.
Your compiler is right: you cannot create a variable of abstract typ. Your class Base is abstract because it declares a pure virtual method, that is a function without any implementation:
virtual void Sub1() = 0;
Your class A derived from Base is abstract, too, because it does not provide an overriding implementation for the method.
You must provide an implementation to all declared virtual methods to make a type instantiable. As you override a pure virtual Sub1() in class B, you can create variables of class B (and its descendant classes), but class A cannot be used itself as an actual type for a variable.
You are extending Base class from A but you didn't implement the pure virtual method in A. So, you need to make A as abstract class. It can't be a concrete class.
To ignore making A as abstract and to use it as a concrete class, just override the pure virtual method too and define it with no statements in it. Now you can create an instance for A.
What I want to add is Since Base is abstract and class A doesn't implement one of its pure virtual function so A is also abstract. As abstract class cant be instantiated (only pointers and references are allowed) we use pointers of abstract class (say pointer to A) to instantiate object of classes derived from abstract class (A or base in this case).
So you need to provide implementation of pure virtual function and have to use pointer to A like
A *a;
a = new B(); // it would compile now
Hope you got my point.

Override member field in derived classes

I have a code snippet below:
#include <iostream>
using namespace std;
class Base {
public:
Base() : b(0) {}
int get();
virtual void sayhello() { cout << "Hello from Base with b: " << b << endl; }
private:
int b;
};
int Base::get() {sayhello(); return b;}
class Derived : public Base {
public:
Derived(double b_):b(b_){}
void sayhello() { cout << "Hello from Derived with b: " << b << endl; }
private:
double b;
};
int main() {
Derived d(10.0);
Base b = d;
cout << "Derived b: " << d.get() << endl;
cout << "Base b: " << b.get() << endl;
}
Run the compiled executable and I find the result is out of my expectation on my llvm-g++ 4.2 machine. The output on my box is as
Hello from Derived with b: 10
Derived b: 0
Hello from Base with b: 0
Base b: 0
What I want to do in the code is to override a member field (b) in Derived class.
Since I think both Base and Derived need to access this field, I define a get member function in Base, thus Derived can inherit it.
Then I try to get the member field from different objects.
The result shows that I still get original b in Base by d.get() instead of that in Derived, which is what I expected the code to do.
Anything wrong with the code (or my understanding)? Is this behavior specified in the specification? What is the right way to override a member field and properly define its getter and setter?
The new b added in the derived class doesn't override base's b. It just hides it.
So, in the derived class you have two b and the virtual method prints corresponding b.
You can't simply override a member field, and as Base::get is compiled, the b variable is resolved to Base::b so this method will always use this value and not a value from another field with the same name in a derived class.
The usual way to override an attribute is to override the way you access it, i.e. override the accessors (getter and setter).
You can achieve something like that by decorating the getter, but the getter return type will always be the same:
class Base {
public:
Base() : b(0) {}
int get();
virtual void sayhello() { cout << "Hello from Base with b: " << b << endl; }
protected:
virtual int getB() {return b;}
private:
int b;
};
int Base::get() {sayhello(); return getB();}
class Derived : public Base {
public:
Derived(double b_):b(b_){}
void sayhello() { cout << "Hello from Derived with b: " << b << endl; }
protected:
int getB() override {return b;} // conversion from double to int
private:
double b;
};
I'm not sure I understand you correctly, but it by "override" you mean "replace", you'd use a template:
#include <iostream>
using namespace std;
template< typename T >
class Base {
public:
Base() : b(0) {}
Base(T b_) : b(b_) {}
T get();
virtual void sayhello() { cout << "Hello from Base with b: " << b << endl; }
protected:
T b;
};
template< typename T >
T Base<T>::get() {sayhello(); return b;}
class Derived : public Base<double> {
public:
Derived(double b_):Base(b_){}
void sayhello() { cout << "Hello from Derived with b: " << this->b << endl; }
};
int main() {
Derived d(10.0);
Base<double>* b = &d;
cout << "Derived b: " << d.get() << endl;
cout << "Base b: " << b->get() << endl;
}
You code in main was also attempting Base b = d; which would lead to slicing, the above fixes that and makes sure you don't accidentially use Base<int> instead of Base<double>.
Live example
you should rewrite your Derived::ctor as follows:
Derived(double _b)
:Base(_b)
{}
And remove filed b in Derived class. Instead mark b in the Base class as protected.
EDIT
Disregard all of this
I've found a problem in your code:
Base b = d;
You're copying derived object to base. It copies only base fields. If you want polymorphism try next:
Base *b = &d;
b->get()

Does f(int) in base class inherited in derived derived class D which have f(double)? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why does an overridden function in the derived class hide other overloads of the base class?
Does f(int) in base class inherited in derived derived class D?
if yes then why overloading is not working here.
and if no then why f(int) is not inherited as class d is publicly derived.
I am confused.
class B {
public:
int f(int i) { cout << "f(int): "; return i+1; }
// ...
};
class D : public B {
public:
double f(double d) { cout << "f(double): "; return d+1.3; }
// ...
};
int main()
{
D* pd = new D;
cout << pd->f(2) << '\n';
cout << pd->f(2.3) << '\n';
}
This is the Classical example for Function Hiding.
The overload resolution in C++ does not work across classes, A function in derived class Hides all the functions with identical name in the Base class. Compiler only sees the function in derived class for an derived class object.
You can Unhide all the base class functions for your derived class by using the using Declaration. in your derive class.
Adding,
using B::f;
in your derived class will enable your derived class object to access all the functions with the name f() int the Base class as if they were overloaded functions in Derived class.
This should be a good read:
What's the meaning of, Warning: Derived::f(char) hides Base::f(double)?
I think if you give a derived class a function with the same name as functions existing in a base class, the derived class' function will hide the base class' functions. If you merely wanted to overload, use the using keyword.
class B {
public:
int f(int i) { cout << "f(int): "; return i+1; }
// ...
};
class D : public B {
public:
using B::f; //brings in all of B's "f" functions
//making them equals of D's "f" functions.
double f(double d) { cout << "f(double): "; return d+1.3; }
// ...
};
int main()
{
D* pd = new D;
cout << pd->f(2) << '\n';
cout << pd->f(2.3) << '\n';
}