I am new to OO programming and I was wondering how to solve the following question -
I have the following:
class A
{
public:
A() {};
~A() {};
virtual functionA() = 0;
}
class B: public A
{
public:
B() {};
~B() {};
functionA();
functionB();
}
Is there a way to access functionB using an object of the base class A? If no, why is it not possible? If yes, how does one do it? I tried to find this answer on this site but I didn't find anything concrete.
I would modify your example slightly to give you a better understanding:
class Animal
{
public:
A() {};
~A() {};
virtual Eat() = 0;
}
class Bird: public Animal
{
public:
B() {};
~B() {};
Eat();
Fly();
}
Should an Animal
object be allowed to access the function Fly
which belongs to Bird
?
No, because not all Animal
s are Bird
s.
But if you are sure than a specific Animal
object is a Bird
, then you can downcast the Animal
object to Bird
and then call Fly
function.
However, this is not generally recommended. Upcasts (casting Bird
to Animal
) are okay because all Bird
s are Animal
s.
In general this is not possible. Class A can't access derived methods in Class B. The general relationship is upward for inheritance. Imagine a Class C that also has functionB, the resolution would be ambiguous.
class A
{
}
class B:public A
{
void functionB() {};
}
class C:public A
{
void functionB() {}
}
main()
{
A a;
a.functionB(); // What to call here?
}
With that being said, if an instance is in fact a B then a downcast could be used.
main()
{
B b;
A&a = b; // ok since a B is-a A
auto & b1 = dynamic_cast<B&>(a); // ok since this particular instance is-a B
b1.functionB();
}
perhaps this is what you were reaching for.
You can access only virtual method of B using the object A. This is called runtime-polymorphism and it is achieved with virtual function. Hence in order to implement the runtime behaviour C++ compiler inserts Virtual Table for every class having virtual function or class inherited from the class that has virtual function.
As in your code, i will make small modification:-
class A
{
public:
A() {};
~A() {};
virtual void functionA() = 0;
virtual void functionC();
}
class B: public A
{
public:
B() {};
~B() {};
void functionA() override; // C++ 11 : override keyword ensures that the function is virtual and is overriding a virtual function from a base class.
void functionB();
}
As the class A contains a virtual function C++ compiler inserts a pointer v_ptr called as virtual table pointer. Compiler also creates a table for that class called as virtual table known as vtable for the class. The table is created compile time v_ptr holds the address of v_table of the corresponding class. vtable is a array of function pointers pointing to virtual function. As functionA is pure virtual so in vtable the address entry for functionA will be null and but functionC has a valid address entry in vtable as it is not pure virtual function.
virtual table contains pointers to functionA() and functionC function of A class. But the implementation is incomplete as functionA is pure virtual. So you can't create object of class A.
As B Class inherits from A class, and as we know A class has a data member v_ptr. B class inherits v_ptr of A class but new virtual table will be created compile time for B class. Hence v_ptr of B class holds the address of vtable of B class. As B class has implemented functionA function. vtable of B class contains pointer to functionA function of B class but pointer to functionC function of base class i.e A class.
A *a = new B();
a->functionA(); //calls B functionA
a->functionC(); //calls A functionC since we haven't overriden this function in B