Calling sub-class method from a base-class pointer? - c++

I didn't know what to give as a title, I expect more experienced stackoverflow.com users to improve it.
Let's say we have the class A
class A {
void hello(){ cout << "i'm an A" << endl; }
}
and its sub-class B
class B: public A {
void hello(){ cout << "i'm a B" << endl; }
}
Then we did somewhere in our program
A* array[2];
array[0] = new A;
array[1] = new B;
array[0]->hello(); // output: "i'm an A"
array[1]->hello(); // output: "i'm a B"
why doesn't the array[1].hello(); output I'm a B since we instanciated a B object for that base-class pointer ? and how to make it happen ?

Couple of changes here:
make function hello in class A, a virtual and public: because by default it is private
class A {
public:
virtual void hello(){ cout << "i'm an A" << endl; }
};
Similarly make hello in class B virtual
class B: public A {
virtual void hello(){ cout << "i'm a B" << endl; }
};

You have to make hello a virtual function:
class A {
virtual void hello() { cout << "i'm an A" << endl; }
};
class B : public A {
virtual void hello() override { cout << "i'm a B" << endl; } // 1)
};
This tells the compiler that the actual function should not be determined by the static type (the type of the pointer or reference) but by the dynamic (run-time) type of the object.
1) The overridekeyword tells the compiler to check, if the function actually overrides a hello function in the base class (helps e.g. to catch spelling mistakes or differences in the parameter types).

Since you have inherited class A in class B, derived class B will call the function from the Base class. You need to override the function in class B, as you want to change the Base class functionality.
You can do this with the override and virtual keywords.
http://en.cppreference.com/w/cpp/language/override

Related

How to execute a virtual function from a base class without the explicit call of Base::func() in a derived class?

I'm a newbie in C++ and have a question. I can't find any related stuff for this question on Google.
Is it possible in C++ for code in a virtual function to be called from the base class without invoking it with Base::func() in the derived class?
Here is an example of what I mean:
class Base {
public:
virtual void func(void) { cout << "Base func()" << endl; }
};
class Derived : Base {
public:
virtual void func(void) { cout << "Derived func()" << endl; }
};
The output should be the following when the function func is called from Derived:
Base func()
Derived func()
Is this even possible in C++? Or, is there another way to implement this behavior?
Is that intention even possible in C++? Or is there a other way to implement this behavior in C++?
You can get that behavior only if you add
Base::func();
in the implementation of Derived::func(). The language does not provide a mechanism to make that automatic.
You can make the base class get the calls first by making the interface non-virtual, and then call the (private) derived function from there:
class Base {
public:
void func()
{
cout << "Base func()" << endl;
derived_func();
}
private:
virtual void derived_func() { }
};
class Derived : Base {
private:
virtual void derived_func() { cout << "Derived func()" << endl; }
};
You have call the base class in derived class implementation to make that happen
class Base {
public:
virtual void func(void) { cout << "Base func()" << endl; }
};
class Derived : Base {
public:
virtual void func(void)
{
Base::function();
cout << "Derived func()" << endl;
}
};
But this is still calling Base::func() from Derived::func()
You can, however, achieve what you want if the func() was actually your constructor.

C++ - const keyword in methods and overload

for which reason this program:
#include <iostream>
using namespace std;
class Base {
public:
Base() { cout << "Costruttore Base" << endl; }
virtual void foo(int) { cout << "Base::foo(int)" << endl; }
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
virtual void bar(double) { cout << "Base::bar(double)" << endl; }
virtual ~Base() { cout << "Distruttore Base" << endl; }
};
class Derived : public Base {
public:
Derived() { cout << "Costruttore Derived" << endl; }
void foo(int) { cout << "Derived::foo(int)" << endl; }
void bar(int) const { cout << "Derived::bar(int)" << endl; }
void bar(double) const { cout << "Derived::bar(double) const" << endl; }
~Derived() { cout << "Distruttore Derived" << endl; }
};
int main() {
Derived derived;
Base base;
Base& base_ref = base;
Base* base_ptr = &derived;
Derived* derived_ptr = &derived;
cout << "=== 1 ===" << endl;
base_ptr->foo(12.0);
base_ref.foo(7);
base_ptr->bar(1.0);
derived_ptr->bar(1.0);
derived.bar(2);
return 0;
}
In the call base_ptr->bar(1.0); is called Base::bar(double), instead in the derived_ptr->bar(1.0); is called Derived::bar(double) const.
I understood that is about the const keyword, but I don't understand why the compiler is choosing different overloaded functions.
If I remove the const keyword, everything is working as expected, calling in both cases the Derived::bar
That's because const changes the signature of the function, so they're different. Either make both the base class and derived class const or not, otherwise one won't override the other.
It's because you're not really overriding the function bar(). You are defining a new function bar() in the derived class with a different signature.
So either remove the const in the derived class or add a const to the signature of bar() in the upper class. (Or keep it as it is but know that you now have two functions named bar() in derived class, one of which is hidden)
C++11 added the override specifier to prevent these kind of surprises. Use, the override keyword, and the compiler will only compile your code, if it does override.
Taking the supposedly override of bar(int) (this also applies to the bar(double):
class Base {
public:
....
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
};
class Derived : public Base {
public:
...
//This isn't an override, program is well formed
void bar(int) const { cout << "Derived::bar(int)" << endl; }
};
The bar member function in Derived did not override the base class' own. Because the const qualifications are different, hence the member function signatures are different. All you did in the derived class was to add a new overload and hide that of the base class'.
Add the override keyword in the derived class' and the compiler will give a diagnostic if it doesn't override.
class Base {
public:
....
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
};
class Derived : public Base {
public:
...
//This isn't an override, program is ill-formed, diagnostic required
void bar(int) const override { cout << "Derived::bar(int)" << endl; }
};
To override, the member function signatures must be the same.
class Base {
public:
....
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
};
class Derived : public Base {
public:
...
//This overrides
void bar(int) override { cout << "Derived::bar(int)" << endl; }
};
So, learn to use the override keyword whenever you want to override, it will save you some headaches.

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.

static_cast parent class to child class C++

Output of this program is "Method B". How can an instance of the parent object call the child class's function through a static_cast?
To make things more confusing, if I make method() virtual, then this code outputs "Method A".
Can anyone explain what is happening here?
class A {
public:
void method() {
cout << "Method A" << endl;
}
};
class B : public A {
public:
void method() {
cout << "Method B" << endl;
}
};
int main() {
A a;
B* bptr = static_cast<B*>(&a);
bptr->method();
}

C++ class member with same name as in base class

How does the this pointer behaves when used inside a base class method:
class Base{
public:
int a;
Base() : a(5) {}
void func(){
std::cout << " value is : " << this->a << std::endl;
}
};
class Derived : public Base{
private:
int a;
public:
Derived() : a(1){}
void func1(){
std::cout << " value is : " << this->a << std::endl;
}
};
int main(){
Derived d;
d.func();
d.func1();
}
the output of the code is :
value is : 5
value is : 1
As i am using the same object to call both the functions. So will the value of this pointer differ in methods for base and derived class ?
this->a is equivalent to a in that context, so it has nothing to do with the base pointer.
The member a is resolved statically, and the derived class hides the base class member, since they're both named a.
To check the this pointer itself, you can print it directly:
std::cout << this;
It will be the same for both objects.
The main thing to take from this is that Base::a and Derived::a are different. Try the following in Derived:
void func1(){
std::cout << "derived value is : " << a << std::endl;
std::cout << " base value is : " << Base::a << std::endl;
}
You would have to do this->Base::a to access Base's a. Else you always access Derived::a.
this pointer will always point to current object in which it exists.
When func is called, Base class is used and base class field is printed. but,
When func1 is called, Derived class is used and it's field is printed.
Try commenting this line Derived() : a(1){} and you'll get more clarity.