Is there a way I can use child methods with a parent class pointer:
#include <iostream>
class Parent {
public:
int a;
virtual int ret() {
return a;
}
};
class Child: public Parent {
int b;
public:
int ret() {
return a;
}
int retB() {
return b;
}
};
void main() {
Parent* parent = new Child();
parent->retB();
}
Im using an array of Parent pointers with derived classes as members.
Is there a simple solution to this or should i just rethink my code?
Out of the blue? No.
With certain checks? Yes.
What do I mean by that? Suppose you have a following class hierarchy:
struct Base {};
struct DerOne : Base {};
struct DerTwo : Base {};
Then you create a pointer of Base type to some derived class:
Base* b_ptr = new DerTwo();
It compiles correctly. Now imagine you want to call DerTwo's imaginary method. In your world, it may be ok, but why it's not?
There would have to be some checks, whether or not what b_ptr points to actually implements the method you want to invoke. These checks are not automatically performed. In C++ you don't pay for what you don't need. It'd be pointless to have those kind of checks every time we call any method via a pointer.
So how can you achieve it?
You have to ensure that b_ptr points to something that implements the method you want to invoke. How?
static_cast vs dynamic_cast:
Base class' pointer cannot invoke methods that are not declared in Base class. That's a fact. Done. If you wish to invoke some method from Derived class, you need to change the type of the pointer. How you do that? You either use static_cast<> or dynamic_cast<>. Here you can read more about C++ casts, but for now, I will tl;dr this question and answer for your specific example.
Option #1: You know that type pointed to by b_ptr is of a certain class (let's assume we're talking about DerTwo) and you want to invoke a foo() method declared inside it.
You use static_cast<>. You use it because you know and are certain that there is a specific, derived type object pointed to by a base class pointer. Regarding our example, it'd look like this:
Base* b_ptr = new DerTwo();
DerTwo* der_ptr = static_cast<DerTwo*>(b_ptr);
der_ptr->foo(); // b_ptr and der_ptr point to the same object
Option #2: You don't know the type of the object pointed by b_ptr and want to check if it's safe to call foo().
Suppose that foo() is declared only in DerTwo. Thus, if b_ptr points to DerOne object and you'd want to call foo(), terrible things would happen. You'd call a non-existing method. You have to perform a check, via dynamic_cast<>:
Base* b_ptr = new DerTwo();
DerTwo* der_ptr = dynamic_cast<DerTwo*>(b_ptr);
if(der_ptr != nullptr){
der_ptr->foo(); // b_ptr and der_ptr again point to the same object
} else {
// b_ptr somehow does NOT point to DerTwo object
}
dynamic_cast<> performs a check, whether or not it's argument actually points to the object of specified type. It it does, it returns a pointer of the specified type to the object. If it fails, it returns nullptr, so all you have to do to check if your dynamic casting succeeded, is compare it's result to nullptr.
Related
class Base {
public:
virtual void test() {};
virtual int get() {return 123;}
private:
int bob = 0;
};
class Derived: public Base{
public:
virtual void test() { alex++; }
virtual int get() { return alex;}
private:
int alex = 0;
};
Base* b = new Derived();
b->test();
When test and get are called, the implicit this pointer is passed in. Is it because Derived classes having a sub memory layout that is identical to what a pure base object would be, then this pointer works for both as a base pointer and derived pointer?
Another way to put it is, the memory layout for Derived is like
vptr <-- this
bob
alex
That is why it can use alex in b->test(), right?
Inside of Derived's methods, the implicit this pointer is always a Derived* pointer (more generically, the this pointer always matches the class type being called). That is why Derived::test() and Derived::get() can access the Derived::alex member. That has nothing to do with Base.
The memory layout of a Derived object begins with the data members of Base, followed by optional padding, followed by the data members of Derived. That allows you to use a Derived object wherever a Base object is expected. When you pass a Derived* pointer to a Base* pointer, or a Derived& reference to a Base& reference, the compiler will adjust the pointer/reference accordingly at compile-time to point at the Base portion of the Derived object.
When you call b->test() at runtime, where b is a Base* pointer, the compiler knows test() is virtual and will generate code that accesses the appropriate slot in b's vtable and call the method being pointed at. But, the compiler doesn't know what derived object type b is actually pointing at in runtime (that is the whole magic of polymorphism), so it can't automatically adjust the implicit this pointer to the correct derived pointer type at compile-time.
In the case where b is pointing at a Derived object, b's vtable is pointing at Derived's vtable. The compiler knows the exact offset of the start of Derived from the start of Base. So, the slot for test() in Derived's vtable will point to a private stub generated by the compiler to adjust the implicit Base *this pointer into a Derived *this pointer before then jumping into the actual implementation code for Derived::test().
Behind the scenes, it is roughly (not exactly) implemented like the following pseudo-code:
void Derived_test_stub(Base *this)
{
Derived *adjusted_this = reinterpret_cast<Derived*>(reinterpret_cast<uintptr_t>(this) + offset_from_Base_to_Derived);
Derived::test(adjusted_this);
}
int Derived_get_stub(Base *this)
{
Derived *adjusted_this = reinterpret_cast<Derived*>(reinterpret_cast<uintptr_t>(this) + offset_from_Base_to_Derived);
return Derived::get(adjusted_this);
}
struct vtable_Base
{
void* funcs[2] = {&Base::test, &Base::get};
};
struct vtable_Derived
{
void* funcs[2] = {&Derived_test_stub, &Derived_get_stub};
};
Base::Base()
{
this->vtable = &vtable_Base;
bob = 0;
}
Derived::Derived() : Base()
{
Base::vtable = &vtable_Derived;
this->vtable = &vtable_Derived;
alex = 0;
}
...
Base *b = new Derived;
//b->test(); // calls Derived::test()...
typedef void (*test_type)(Base*);
static_cast<test_type>(b->vtable[0])(b); // calls Derived_test_stub()...
//int i = b->get(); // calls Derived::get()...
typedef int (*get_type)(Base*);
int i = static_cast<get_type>(b->vtable[1])(b); // calls Derived_get_stub()...
The actual details are a bit more involved, but that should give you a basic idea of how polymorphism is able to dispatch virtual methods at runtime.
What you've shown is reasonably accurate, at least for a typical implementation. It's not guaranteed to be precisely as you've shown it (e.g., the compiler might easily insert some padding between bob and alex, but either way it "knows" that alex is at some predefined offset from this, so it can take a pointer to Base, calculate the correct offset from it, and use what's there.
Not what you asked about, so I won't try to get into detail, but just a fair warning: computing such offsets can/does get a bit more complex when/if multiple inheritance gets involved. Not so much for accessing a member of the most derived class, but if you access a member of a base class, it has to basically compute an offset to the beginning of that base class, then add an offset to get to the correct offset within that base class.
A derived class is not a seperate class but an extension. If something is allocated as derived then a pointer (which is just an address in memory) will be able to find everything from the derived class. Classes don't exist in assembly, the compiler keeps track of everything according to how it is allocated in memory and provides appropriate checking accordingly.
I'm working with a library written in C, which does inheritance like so:
struct Base
{
int exampleData;
int (function1)(struct Base* param1, int param2);
void (function2)(struct Base* param1, float param2);
//...
};
struct Derived
{
struct Base super;
//other data...
};
struct Derived* GetNewDerived(/*params*/)
{
struct Derived* newDerived = malloc(sizeof struct Derived);
newDerived->super.function1 = /*assign function*/;
newDerived->super.function2 = /*assign function*/;
//...
return newDerived;
}
int main()
{
struct Derived *newDerieved = GetNewDerived(/*params*/);
FunctionExpectingBase((struct Base*) newDerived);
free(newDerived);
}
It is my understanding this works because the pointer to Derived is the same as the pointer to the first member of Derived, so casting the pointer type is sufficient to treat an object as its "base class." I can write whatever gets assigned to function1 and function2 to cast incoming pointer from Base* to Derived* to access the new data.
I am extending functionality of code like this, but I am using a C++ compiler. I'm wondering if the below is equivalent to the above.
class MyDerived : public Base
{
int mydata1;
//...
public:
MyDerived(/*params*/)
{
function1 = /*assign function pointer*/;
function2 = /*assign function pointer*/;
//...
}
//...
};
int main()
{
MyDerived *newDerived = new MyDerived(/*params*/);
FunctionExpectingBase( static_cast<Base*>(newDerived) );
delete newDerived;
}
Can I expect the compiler to lay out the memory in MyDerived in the same way so I can do the same pointer cast to pass my object into their code? Or must I continue to write this more like their C architecture, and not take advantage of the C++ compiler doing some of the more tedious bits for me?
I'm only considering single inheritance for the scope of this question.
According to Adding a default constructor to a base class changes sizeof() a derived type and When extending a padded struct, why can't extra fields be placed in the tail padding? memory layout can change even if you just add constructor to MyDerived or make it non POD any other way. So I am afraid there is no such guarantee. Practically you can make it work using proper compile time asserts validating the same memory layout for both structures, but such solution does not seem to be safe and supported by standard C++.
On another side why your C++ wrapper MyDerived cannot inherit from Derived? This would be safe (as it can be safe when Derived is casted to Base and back, but I assume that is out of your control). It may change initialization code in MyDerived::MyDerived() to more verbose, but I guess that is small price for proper solution.
For your problem it does not really matter since the "client" code only cares about having a valid Base* pointer: they aren't going to downcast it in Derived or whatever, or copy it.
I tried this which didn't work:
void Map::OnLMClick(short xPos, short yPos)
{
SObject* pSObject = pEditWindow->GetSelectedItem();
if (pSObject==SOTile)
{
/* Do */
I tried this as a test:
SObject* EditorWindow::GetSelectedItem()
{
return pSOTile[1]; //pSOTile[1] is a valid pointer, member of EditorWindow
}
SOTile class is a child of base class SObject. So, is it possible to create a Base* to get one of its child's* returned and then have the program react differently depending of what child it returned? If it is the case, how do I then have access to members of it's child that are not members of base?
If your types are polymorphic (i.e. if they have at least one virtual function), you can use dynamic_cast:
Base* pObject = get_object(); // May return a pointer to Derived
Derived* pDerived = dynamic_cast<Derived*>(pObject);
Notice, that dynamic downcasts are sometimes an indicator of bad design. Try to think if a better arrangement of virtual functions in your hierarchy would help.
Without knowing the concrete application domain, it is not possible for me to give more concrete advices.
dynamic_cast operator performs a special checking when a class is polymorhic.
SOTile* pSOTile = dynamic_cast<SOTile*>(pSObject);
if (pSOTile)
{
/* Do */
}
Since SOTile is a pointer to a type that derives from SObject, you should not need to cast at all, since the compiler should be able to automatically resolve an SObject pointer from the derived pointer and then compare the two SObject pointers together (the same way that you can assign a derived pointer to a base pointer without type-casting). Some compilers, like Borland's, support that just fine, eg:
class Base
{
};
class Derived : public Base
{
};
Derived *d = ...;
Base *b = ...;
if (b == d) // <-- compiles fine
However, if for whatever reason your compiler does not allow that, you can manually cast the derived pointer using static_cast (don't use dynamic_cast to cast the base pointer):
if (pSObject == static_cast<SObject*>(SOTile))
If SOTile is not a pointer to a type that derives from SObject, static_cast will fail at compile-time.
I wouldn't recommend to use dynamic_cast. Instead, you can implement that different behavior in different child class. Sometimes called as "template method" pattern
I have a set of objects derived from common base, ApiObject. I need to be able to register all ApiObjects in a separate data structure, but I need to have an actual address of the object being created, not the base class (I'm using multiple inheritance).
I can't put the code to register an object in ApiObject constructor, because it does not know the address of the derived object; nor can I put it in the derived classes' constructors, because we have no way of knowing whether we are actually constructing another derived class (e.g. if class B is inherited from A, and both can be constructed).
So the only option I see is to explicitly call the registration function every time we create an object, as in
B* b = new B(...);
RegisterObject(b);
However, this doesn't seem to be a very good solution, as I have to remember to call this function every time.
I suppose I should give more context to explain why I'm doing this. The objects are created via an overloaded new operator, and it needs the object to know the context it was created in (Lua state). E.g.
Foo* object = new(L) Foo(...);
// Foo is derived from ApiObject, and we want ApiObject to have a reference to L
Currently it is done in a somewhat unelegant way - the new operator allocates additional bytes before the object and stores the L pointer in there, along with some additional data to describe the object type. The base class then receives a pointer to this 'metadata' via the init function.
Otherwise, the first thing that comes to mind are virtual functions, but they can't be called from the constructor, so I'd have to register the base ApiObject pointer but only call the virtual function at some later point, and I'm not sure that's prettier than my current implementation.
What is the type required for RegisterObject? If it takes a
Base*, then you can call it from the constructor of Base,
regardless of the final hierarchy. If it takes some other type,
then you want to call it from the constructor of that type; you
do not want to call it from all classes derived from Base,
but only for those derived from whatever type it takes.
If RegisterObject takes a Base*, and you call it from a
function in a derived class, the first thing that will occur is
that the pointer you pass it will be converted to a Base*.
RegisterObject never receives a pointer to the derived object,
only to the Base in the derived object.
You can additionaly derieve every object you want to register from CRTP class, which performs registration, e.g.
template<class T>
struct registarar_t<T>
{
registarar_t()
{
register(derived());
}
T* derieved()
{
return static_cast<T*>(this);
}
}
struct IWantToRegister : registrar_t<IWantToRegister>, ApiObject
{
}
Also, be careful, derived() pointer is right, but object is not yet initialized (accessing it in parent constructor)
Maybe kassak's solution is more elegant, I'm not that advanced, but I'd recommend something like this (register shoudl be called in the constructor so you don't have to write it every time:
#include <iostream>
struct ApiObject;
void registerObj(ApiObject *foo);
struct ApiObject{
public:
ApiObject(std::string n){
name = n;
registerObj(this);
}
std::string name;
};
void registerObj(ApiObject *foo){
std::cout<<"register called on "<<foo->name<<"\n";
}
struct A : public ApiObject{
public:
A(std::string n) : ApiObject(n) {
std::cout<<"init A\n";
}
};
struct B : public ApiObject{
public:
B(std::string n) : ApiObject(n) {
std::cout<<"init B\n";
}
};
int main(){
B *b = new B("b obj");
A *a = new A("a obj");
delete b;
delete a;
}
You can call the registration function from the base constructor. Just make the base destructor virtual. The address will be same for base and derived class. Just don't use the pointer address before the whole object is created.
Once all the objects are fully created, the pointer address can be safely used through virtual functions or dynamic-casted to derived class.
In my project I have a scenario like suppose:
1) BaseClass is an interface which derives from a parent class IFlow
2) ChildClass derives from it ie from Base class
3) In childClass Init function I am using dynamic_cast to cast the objet of IFlow to BaseClass which is as shown below:
void ChildClass::init()
{
IFlow* pFlow = someMethod(); //it returns the IFlow object pointer
//this works for static cast but fails for dynamic cast
BaseClass *base = dynamic_cast<BaseClass*>(pFlow) ;
}
In the above code the 2nd line of dynamic _cast returns zero but if the dynamic_cast is changed to static_cast then the code works as expected .
Please advice
dynamic_cast will "not work" in two instances:
You have somehow compiled your code without RTTI. Fix your compiler settings.
The entire purpose of dynamic_cast is to ensure that the cast actually works. Casting from child to parent always works because every child of some type is guaranteed to be that type (the whole "all dogs are animals, but not all animals are dogs" thing). Casting from a parent to a child can fail if the object is not actually that child type. dynamic_cast will return a null pointer if the IFlow you give it is not actually a BaseClass.
Furthermore, your static_cast does not work. It simply returns a value. A value which, if you ever use it, results in undefined behavior. So it only "works" in the sense that it returned a value you could attempt to use.
So one of these two things happened. Which one is up to you to find, since you didn't give us the implementation of someMethod.
A dynamic_cast<> returns null (zero) if the cast is not legal. In this case it's doing what you want: there is a problem somewhere in your inheritance tree. (The static_cast<> "works" only because it's a sledgehammer; it forces the cast at compile time without any knowledge of the type that the pointer will actually have at runtime.)
if it like this?:
class A
{
public:
A(){a = 0;};
virtual ~A(){};
protected:
int a;
};
A *GetAInstance();
class B : public A
{
public:
B() : A() {b = 1;};
virtual ~B(){};
protected:
int b;
};
class C: public B
{
public:
C() : B() {};
~C(){};
void CheckA()
{
A *pA = GetAInstance();
B *pB = dynamic_cast<B*>(pA); --> Here pB is NULL.
B *pB2 = static_cast<B*>(pA);
};
};
A *GetAInstance()
{
A *pA = new A();
return pA;
};
int _tmain(int argc, _TCHAR* argv[])
{
C *pC = new C();
pC->CheckA();
return 0;
}
This is because you are trying to set a parent pointer to its child pointer. In dynamic_cast it thinks it is not safe, so it set the child pointer to NULL, you can see pB above which is NULL. For child class may have more functions/member variables, you call these new functions/member variables would cause run time error. But static_cast doesn't care this, it is only a compiler time check not run time check. static_cast only cares if they have some relation ship. If they have, static_cast convert the pointer even doesn't care run time error. Please run this small sample and check pB2 is not NULL. :)
Hope useful. Thanks! :)
What type is being returned by someMethod()? It needs to be derived from BaseClass to allow dynamic_cast to work. You can't cast downwards if it's not the correct type.
Static cast works at compile time and the compiler will just turn the pointer over.