简体   繁体   中英

Through base class's pointer we can't access derived class specific members

A Base Class pointer can point to a derived class object. Why is the vice-versa not true?

That thread says that we can't make the derived class point to base class because the derived class may not have access to all the members of base class.

The same is true vice versa also. The base class won't even have access to the members which are specific to derived classes.

#include <iostream>

using namespace std;

class BaseClass
{
public:
    virtual void baseFx();
};

void BaseClass::baseFx()
{
    std::cout << "From base virtual function\n";
}

class DerivedClass : public BaseClass
{
public:
    void baseFx();
    void h() { std::cout << "From derived class. h()\n"; }
};

void DerivedClass::baseFx()
{
    std::cout << "From derived virtual function\n";
}

int main()
{
    BaseClass* objBaseclassB = new DerivedClass();
    objBaseclassB->baseFx (); // Calls derived class's virtual function.
    objBaseclassB->h(); // error: 'class BaseClass' has no member named 'h'.

    return 0;
}

So, why is the restriction only for derived class? Why is this not allowed considering the above logic? DerivedClass* objBaseclassC = new BaseClass();

Assigning a Derived class object to Base class pointer is valid and the cornerstone of polymorphism.

Yes, the Derived class may have additional members which cannot be accessed via a base class pointer, which is okay because you, the programmer are doing such an assignment while being fully aware that you cannot access those members . You are doing it purely for the purpose of polymorphism. Which means you will only be calling virtual functions which will use the vtables to call the correct override based on which object the pointer is pointing to.

However, casting a base class pointer back to a derived class pointer is not straightforward. You need type information and it is only possible if the Base class is polymorphic (ie. has virtual functions) and the class you are casting to is derived from the Base class. This exact check is performed by dynamic_cast . dynamic_cast checks if the downcast is possible and returns the Derived class pointer if it is valid. Otherwise it returns nullptr .

Coming to your final question: DerivedClass* objBaseclassC = new BaseClass(); is not valid because accessing any "extra" members in DerivedClass results in a crash.

But when you do BaseClass* derivedPointer = new DerivedClass(); Such a construction will result in a compile time error.

Let me try and explain this in a logical way.

Inheritance in OO programming is used to implement an "is a" relationship between different classes. Eg. If there is a class Animal and a class Dog, we know a Dog "is an" Animal and hence Dog would extend Animal. Hence it would obviously exhibit a lot of functionality (eg. eat() - function) that is common amongst other animals (classes) say Horse. Thus, we tend to put such common code into the base class Animal and keep code specific to each sub-class in the derived classes. (Eg. bark() for Dog)

Hence, it only makes sense to allow a base class type pointer to point to a derived class object, ie, Animal * horse1 = new Horse(); as after all a horse is an animal. The other way around doesn't make sense as every Animal is not necessarily a horse.

PS: as far as C++ is concerned, inheritance is mainly just a re-use mechanism for common code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM