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.
Related
I was trying to understand how the this and the *this keywords work in C++. From my understanding, this returns a pointer to the current instance of the object for which it is called, whereas *this returns a clone of the very same instance.
I saw a version of the below code being used in an algorithms question in a different, unrelated place. I have only kept the parts of the code that pertain to my query.
#include <iostream>
class Base
{
public:
int a, b;
void haha()
{
std::cout << "haha!!!" << std::endl;
}
};
class Derived : public Base
{
public:
int c, d;
void method()
{
Base b(*this);
b.haha();
}
};
int main()
{
Derived d;
d.method();
return 0;
}
I am not able to wrap my head around how *this (a copy of the current Derived class object) is being used to instantiate an object of the Base class.
What is the OOP principle in play here?
Both this and *this are not functions and therefore do not return anything. *this refers to the object pointed to by this. There is no copying involved by just writing
*this; // yes, that's a valid statement, although it has no effect
What would constitute a copy would be one of these:
Derived copy1(*this);
Derived copy2{*this};
However, the copying is done just as it would be if you called the constructor outside of the Derived member function:
Derived copy{d};
However, since Derived is a Base, writing Base b(*this); will call the copy constructor of Base with the Base sub-object of *this. That copies the Base portion, i.e. members int a and int b. It would be like doing this:
Base& dref{d}; // does not copy, slices d
Base b{dref}; // now we copy d as if it was a Base
Note that calling Base::haha would have always printed "haha!!!" because Derived inherits that function and thus calling it without creating a Base copy would have called the same function.
Let's say I have a class A that inherits from its parent class B, and there is another class C that also inherits from class B. Is there a way to change this pointer of class A to class C at run time?
class A : public B {
A::someFunction() {
//can I change this pointer to class C here?
}
}
class C : public B {
...
}
You cant and you shouldn't. The reason is pretty simple. Take a look at this code,
class Base {
public:
Base() {}
virtual void SayHello() {}
};
class A_Derived : public Base {
public:
A_Derived() {}
virtual void SayHello() override { ... }
void SayAllo() { ... }
};
class B_Derived : public Base {
public:
B_Derived() {}
virtual void SayHello() override { ... }
void SayBello() { ... }
};
Now when is we assign the A_Derived class pointer to B_Derived, the compiler will allow to call the SayBello method. This is because for the compiler, its a B_Derived class pointer, it doesn't know about the actual pointer data is pointing at a data block of A_Derived (because inheritance is not compile time, its runtime). So what happens when you call SayBello using that pointer? Its gonna be undefined behavior. You see the issue?
This is why you cant do it (logically and also using C++ style casting).
Is there a way to dynamically change an object to another type?
No. The type of an object cannot change through its lifetime.
Let's say I have a class A that inherits from its parent class B, and there is another class C that also inherits from class B. Is there a way to change this pointer of class A to class C at run time?
No.
At best, you could destroy the original object, and reuse its memory to create another object. Obviously the size and alignment of the memory must be sufficient for the new type. Any reference (which includes pointers such as this in a member function) to the old object will have been invalidated by the destruction of the original object. Reuse of storage is an advanced topic which I don't recommend to beginners.
There is no valid way to do this for one simple reason - in your class inheritance structure, an object of class A cannot be also an object of class C. In C++, two objects of different types can have the same address if and only if one of the objects is a subobject of the other, which is not your case. If you cast a pointer to A to a pointer to C, the pointer will still refer to an object of type A, and dereferencing the casted pointer would result in undefined behavior.
Most probably, what you want to do is to create an object of class C from an object of class A. You can use a converting constructor or a conversion operator to implement this.
Note that if what you really want is to reuse the storage allocated for the object of type A, you will still need to destroy the object A first and then construct the object C. You will have to save any relevant data from A before destroying it to be able to construct C with the data.
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.
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.
Today I found the following disturbingly ambiguous situation in our code base:
class Base {
public:
virtual void Irrelevant_Function(void) = 0;
protected:
C_Container * Get_Container(void);
};
class A : public Base, public Not_Important {
public:
inline C_Container * Get_Container(void);
};
class B : public Base, protected SomethingElse {
public:
C_Container * Get_Container(void);
};
Many things were calling the Get_Container method, but not always calling the correct one - note that none of these functions were virtual.
I need to rename the methods Get_Base_Container, Get_A_Container, etc to remove the ambiguity. What rules does C++ use to determine which version of a function it should call? I'd like to start from the "known state" of what should have been getting called, and then figure out the bugs from there.
For example, if I have a pointer to a Base and call Get_Container, I assume it would just call the Base version of the function. What if I have a pointer to an A? What about a pointer to a B? What about an A or B on the heap?
Thanks.
It depends how you're calling the function. If you're calling through an A *, an A & or an A, then you'll be calling A::Get_Container(). If you're calling through a Base *, a Base & (even if they point to/reference an A), then you'll be calling Base::Get_Container().
As long as there's no virtual inheritance going on, it's quite easy. If you're working directly with an object, it's the object's method that gets called; if you're working with a pointer or reference, it's the type of the pointer or reference that determines the method, and the type of the object pointed to doesn't matter.
A method is first looked up according to the object's static type. If it is non-virtual there, you're done: that's the method that's called. The dynamic type is what virtual methods, dynamic_cast, and typeid use, and is the "actual" type of the object. The static type is what the static type system works with.
A a; // Static type and dynamic type are identical.
Base &a_base = a; // Static type is Base; dynamic type is A.
a.Get_Contaienr(); // Calls A::Get_Container.
a_base.Get_Container(); // Calls Base::Get_Container.
B *pb = new B(); // Static type and dynamic type of *pb (the pointed-to
// object) are identical.
Base *pb_base = pb; // Static type is Base; dynamic type is B.
pb->Get_Container(); // Calls B::Get_Container.
pb_base->Get_Container(); // Calls Base::Get_Container.
I've assumed above that the protected Base::Get_Container method is accessible, otherwise those will be compile errors.
A couple of additional points to note here:
Name lookup occurs in a single scope; E.g. When calling the method on an object with static type 'B', the compiler considers the interface of 'B' to determine whether or not there is a valid match. If there is not, it only then looks at the interface of Base to find a match. This is why that from the compiler's view, there is no ambiguity and it can resolve the call. If your real code has overloading etc. this may be an issue.
Secondly, it is often forgotten that the 'protected' keyword applies at class and not object level. So for example:
class Base {
protected:
C_Container * Get_Container(void);
};
class B : public Base{
public:
C_Container * Get_Container(void)
{
B b;
// Call the 'protected' base class method on another object.
return b.Base::Get_Container();
}
};