Can't access derived class method from pointer of type base class
You can't.
A pointer of type Person
can only be used to access data/addresses(functions) that are part of the Person
object. The compiler simply has no way of knowing what all classes could be deriving from Person
and hence which operations are legal.
Have a look at Dynamic casting. MSDN Reference | Tutorial
In brief:
Player* pPlayer = dynamic_cast<Player*>(pPerson);
if (pPlayer) {
//Use the pointer like a player pointer
//Note: You can only call player functions from pPlayer, not pPerson
} else {
//Use the pointer like a person pointer
}
Note that this casting is a runtime operation. At compile time, the compiler sees you using the Player
pointer to access Player
code, which it is happy to allow!
Disclaimer: I found your code tough to follow, so consider this an answer to your question in text
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"; }
};
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.
Why `this` can't access the derived class members from base class methods when called for derived class object
Me: When the compiler compiles Base::get function, it cannot see Derived::put function.
You : Isn't the Derived::put in the same file? Why can't the compiler see that?
Me: What if there is a Derived1::putttttt defined by somebody 4 years later deriving from Base in another file?
You: mm, maybe I understand.
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
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;
}
};
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
Is there a way to call derived class functions with base class pointer without virtual
Since I could not get any answer from anyone, let me float an option here which I have thought of. This might be a hack though. I am open for correction/comments and criticism as well. :)
The deal is to do reinterpret_cast in the base class functions.
#include <iostream>
#include <vector>
bool preState = true;
class Derived;
class Base;
class Base {
public:
unsigned char a;
int b;
Base() : a('a'), b (2) { };
unsigned char get_a() const;
int get_b() const;
} __attribute__ ((__packed__)) ;
class __attribute__ ((__packed__)) Derived : public Base {
public:
unsigned char c;
int d;
Derived() : c('c'), d(4) { };
unsigned char get_a() const;
int get_b() const;
};
unsigned char Base::get_a() const {
if (preState) {
return a;
} else {
const Derived* d = reinterpret_cast<const Derived*>(this);
return d->get_a();
}
}
int Base::get_b() const {
if (preState) {
return b;
} else {
const Derived* d = reinterpret_cast<const Derived*>(this);
return d->get_b();
}
}
unsigned char Derived::get_a() const {
return c;
}
int Derived::get_b() const {
return d;
}
int main() {
std::vector<Base*> bArray;
bArray.push_back(new Base());
bArray.push_back(new Base());
std::vector<Base*>::iterator bArrayIt = bArray.begin();
for (; bArrayIt != bArray.end(); ++bArrayIt) {
std::cout << (*bArrayIt)->get_a() << " ";
std::cout << (*bArrayIt)->get_b() << std::endl;
}
preState = false;
std::vector<Base*> dArray;
bArrayIt = bArray.begin();
for (; bArrayIt != bArray.end(); ++bArrayIt) {
// Write copy constructor in Derived class which copies everything from
// base object to Derived object
Base* b = new Derived();
dArray.push_back(b);
}
std::vector<Base*>::iterator dArrayIt = dArray.begin();
for (; dArrayIt != dArray.end(); ++dArrayIt) {
std::cout << (*dArrayIt)->get_a() << " ";
std::cout << (*dArrayIt)->get_b() << std::endl;
}
}
The output of this would be:
a 2 // Base class get_a() and get_b()
a 2 // Base class get_a() and get_b()
c 4 // Derived class get_a() and get_b()
c 4 // Derived class get_a() and get_b()
Related Topics
How Many Decimal Places Does the Primitive Float and Double Support
How to Initialize an Array of Struct in C++
How to Assign a Value to the Pointer 'This' in C++
Unit Test That a Class Is Non Copyable, and Other Compile-Time Properties
How to Initialize a Struct to 0 in C++
Boost.Python Call by Reference:Typeerror: No To_Python (By-Value) Converter Found for C++ Type:
Find Available Network Interfaces in C/C++
Partial Specialization of Function Templates
Is Constexpr a "Hint" (Like Inline) or "A Binding Request" to the Compiler
Cmake Link Library Target Link Error
Why Does Adding 0 to the End of Float Literal Change How It Rounds (Possible Gcc Bug)
Element Count of an Array in C++
Stl Container with Std::Unique_Ptr's VS Boost::Ptr_Container
Use Const Wherever Possible in C++
C++ Array Size Dependent on Function Parameter Causes Compile Errors