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 doBaseClass* 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 seevoid Enemy::describe()
pointers/references on
Dragon
only seevoid Dragon::describe(int)
(but could explicitly have access tovoid 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
Class Type Non-Type Template Parameter Initialization Does Not Compile
Can MACros Be Overloaded by Number of Arguments
Are There Any Tricks to Use Std::Cin to Initialize a Const Variable
Returning to Beginning of File After Getline
Dynamically Allocated Memory After Program Termination
Creating a Zip File on Windows (Xp/2003) in C/C++
Qt/C++ - Accessing Mainwindow UI from a Different Class
"Symbol(S) Not Found for Architecture X86_64" on Qtcreator Project
Understanding the Example on Lvalue-To-Rvalue Conversion
Why How to Access Private Variables in the Copy Constructor
Downcasting Shared_Ptr<Base> to Shared_Ptr<Derived>
How to Download the Visual C++ Command Line Compiler Without Visual Studio
How to Convert Unsigned Char* to Std::String in C++
What Is the Underlying Type of a C++ Enum