C++ Access Derived Class Member from Base Class Pointer

C++ Access derived class member from base class pointer

No, you cannot access derived_int because derived_int is part of Derived, while basepointer is a pointer to Base.

You can do it the other way round though:

Derived* derivedpointer = new Derived;
derivedpointer->base_int; // You can access this just fine

Derived classes inherit the members of the base class, not the other way around.

However, if your basepointer was pointing to an instance of Derived then you could access it through a cast:

Base* basepointer = new Derived;
static_cast<Derived*>(basepointer)->derived_int; // Can now access, because we have a derived pointer

Note that you'll need to change your inheritance to public first:

class Derived : public Base

C++ How to access derived class member from base class pointer without using a static_cast or dynamic_cast?

The visitor pattern use double dispatch to allow you to use class-specific member function and member variable (opposed to member function/variable available through the hierarchy).

To implement the visitor pattern, you need a visitor and a hierarchy of visited (in your example it's Base and the classes derived from Base).
With your example it would give something like that:

class Base
{
public:
virtual ~Base() {}
virtual void visit(Visitor) = 0;
};

class Derived : public Base
{
protected:
int someVar = 2;

public:
int getSomeVar () {return this->someVar;}
void visit(Visitor& v) {
v.visit(this);
}
};
class Visitor {
public:
void visit(Derived& d) {
bar(d.someVar);
}
};

The idea behind the visitor is that this of Derived know it's real type while a polymorphic variable (a Base& or Base*) don't. OverridingBase::visit allow you to call the visit who will do the dispatch to the right Visitor::visit.

If you don't override Base::visit, when calling it on a Base& (or Base*) it will call the function on a Base object (so this will be of type Base*). That's why in the example Base::visit is abstract, doing otherwise will only make error more likely to happen (like forgetting to override visit).

When adding a new type in the Base hierarchy (for example a Derived2 class), you will need to add two functions: Derived2::visit and Visitor::visit(Derived2) (or Visitor::visit(Derived2&)).

EDIT

live example

Access member of derived class from pointer of base class

I cannot access members belonging to the derived class with pointer notation

This is by design: you did not tell the compiler that the object pointed to by the pointer is of the derived type.

is it possible for me to access these members with a simple command

You can do it if you perform static_cast<B*>(arr[0]) if you are 100% certain that the pointer points to B, but casting solution should be used as the last resort. Instead, you should derive a member function in the base class, and provide an implementation in the derived class:

class A {
public:
int foo;
virtual char get_bar() = 0;
};

class B : public A {
char bar;
public:
char get_bar() {
return bar;
}
};

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

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.

Base-class pointer pointing to a derived class cannot access derived-class method

In fact you have:

class Enemy {
public:
virtual void describe() { std::cout << "Enemy"; }
};

class Dragon : public Enemy {
public:
// void describe() override { Enemy::describe(); } // Hidden
virtual void describe(int dummy) { std::cout << "Dragon"; }
};

Selection of overload method is done statically:

  • pointers/references on Enemy only see void Enemy::describe()

  • pointers/references on Dragon only see void Dragon::describe(int) (but could explicitly have access to void Enemy::describe()).

Then virtual dispatch is done with runtime type.

So

Dragon foo;
Enemy* pe = &foo;

foo.describe(); // KO: Enemy::describe() not visible (1)
foo.Enemy::describe(); // OK: Enemy::describe()
foo.describe(1); // OK: Dragon::describe(int)

pe->describe(); // OK: Enemy::describe()
pe->describe(1); // KO: No Enemy::describe(int)
pe->Dragon::describe(1);// KO: Dragon is not a base class of Enemy

(1) can be fixed by changing Dragon with

class Dragon : public Enemy {
public:
using Enemy::describe; // Unhide Enemy::describe()

virtual void describe(int dummy) { std::cout << "Dragon"; }
};

Accessing derived class members with a base class pointer

It is possible by using a cast. If you know for a fact that the base class pointer points to an object of the derived class, you can use static_cast:

Entity* e = /* a pointer to an entPlayer object */;
entPlayer* p = static_cast<entPlayer*>(e);
p->setName("Test");

If you don't know for sure, then you need to use dynamic_cast and test the result to see that it is not null. Note that you can only use dynamic_cast if the base class has at least one virtual function. An example:

Entity* e = /* a pointer to some entity */;
entPlayer* p = dynamic_cast<entPlayer*>(e);
if (p)
{
p->setName("Test");
}

That said, it would be far better to encapsulate your class's functionality using polymorphism (i.e. virtual functions).

Speaking of virtual functions, your class hierarchy as implement has undefined behavior: you can only delete an object of a derived type through a pointer to one of its base classes if the base class as a virtual destructor. So, you need to add a virtual destructor to the base class.



Related Topics



Leave a reply



Submit