I have a class A and class B which inherits from class A. Class B has a variable and a function that are not available in class A. I made a pointer
A* ptr=new B();
So how can ptr access the variable and function that belongs to class B?
Class A simply cannot "see" the functions of class B. Instead, you'd have to use something like a dynamic_cast from A to B, check for null, and then proceed as you like. Here is a nice tutorial to explain this a lot better than I can. Each of the casts have their advantages and disadvantages; learn them well. Also, try to avoid C style casting.
EDIT : Seems I misread the question. The answer is still correct, though. Class A would not be able to "see" the variables of Class B. The casting would still allow you access to them.
You can force the derived class to implement a pure virtual method defined in the base class:
class A
{
public:
virtual void do_things() = 0;
};
class B : public A
{
public:
virtual void do_things()
{
//Implementation
}
};
This way you can call the method implemented by class B through a pointer A*:
A* a_ptr = new B();
//The method implemented in class B will be called
a_ptr->do_things();
You could also make the assumption that a_ptr points to an object of class B. If a_ptr doesn't point to a B the pointer returned by dynamic_cast<B*> will be a nullptr. You can use static_cast<B*> if there are no virtual methods in A.
b_ptr = dynamic_cast<B*>(a_ptr);
b_ptr->do_things;
This way you don't need the pure virtual function in class A.
Related
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.
I have to design the specific architecture of the project. I got stuck while trying to create the pointer to the virtual class, and got Segmentation fault (seems my pointer was not assigned correctly).
Below I included the draft of what I'm trying to do.
// Class A has to be pure virtual. It will be inherited by many classes in my project.
class A:
{
public:
virtual void myFunction() = 0;
}
// Class B implements the method from the class A
#include <A.h>
class B: public A
{
public:
void myFunction(); // IS IMPLEMENTED HERE!!
}
// Class C creates a pointer to the class A.
#include <A.h>
class C:
{
A *ptr;
ptr->myFunction(); //Here I want to run myFuction() from the class B.
}
How can I make a connection between those three, so I get the result I want.
I can't change the architecture, or simply omit any of the classes A, B or C.
Thanks for help!
The virtual calls allow to access a function from an object through a pointer or reference of a base type. Note that the object itself needs to be of the type that implements the functionality.
So, in class C you can have something like:
B b;
A *ptr = &b;
ptr->myFunction()
or
A *ptr = new B();
ptr->myFunction()
Either way, you need to create an object of type B, and assign it to a pointer of type A*.
I have here this abstract base class called base_class defined as it follows:
class base_class
{
public:
virtual ~base_class() = 0 {}
virtual size_t area() const = 0;
protected:
base_class() {}
};
One derived class from with it:
template <typename T> class A : public base_class
{
public:
A();
~A();
size_t area() const;
void display();
(...) etc code
};
And another class still derived from it:
template <typename T> class B : public base_class
{
public:
B();
~B();
size_t area() const;
void set();
(...) etc code
};
Than I have this instantiation and function call:
base_class *p = new A<int>;
p->display();
delete p;
p = new B<float>;
p->set();
(...) code
As you might already have observed, is that the pointer p won't "see" display and set methods.
The question is: when using pointers of type base_class, is there a chance of letting a derived object call derived methods that are only defined in the class that it points to? Thus being able to access display and set methods without having to make them virtual in the base class.
Otherwise we would have to make 2 virtual functions in the base_class, display and set, and that's very inconvenient, because A doesn't have to inherit set method, and B the display method.
You can use dynamic_cast to downcast from base class to derived class, if could not determine the runtime type of the object.
base_class *p = new A<int>;
if (A<int> *pa = dynamic_cast<A<int> *>(p))
pa->display();
delete p;
p = new B<float>;
if (B<float> *pb = dynamic_cast<B<float> *>(p))
pb->set();
If the type of object could be confirmed at compile time, static_cast can do the cast too, but beware: You are telling the compiler that you know for a fact that what is being pointed to really is of that type. If you are wrong, then the cast cannot inform you of the problem (as could dynamic_cast, which would return a null pointer if the cast failed, or throw a std::bad_cast for a reference cast failure) and, at best, you will get spurious run-time errors and/or program crashes.
Anyway, the best practice should be rearrange the inheritance relationship, try to use virtual function, avoid downcasts.
I am not quite sure what you ultimately want to do but its not usually good practice to call a function from the derived class that is not virtual in the base class using a pointer to a base class. As was already mentioned, you can use type casting to achieve this, but you need to check if the dynamic_cast was possible before attempting to call the function.
Have you considered creating a pure virtual function in the base class such as:
public:
virtual void doIt() = 0;
Then you could implement this in the derived classes to call the function you want:
class A
{
void doIt()
{
display();
}
};
class B
{
void doIt()
{
set();
}
};
There's actually no way of accessing the members since for all the program knows it wouldn't have to be a derived class, and could just be the base class. This meaning casting as mentioned in the comments.
A pointer is simply an integer, for 32bit OS's it's a 32 bit int, for 64bit well i guess you could guess right? 64bit integer.
When it comes to typing pointers to actual classes and structures etc, it's up to the API to decide whether or not to display the function, it's more of a helper.
As for the program only knows it's a base class pointer you can only access it's variables. However if you are 100% sure what you are dealing with and you want to save performance here's something somewhat pseudo code.
typedef void (A::*func)(void*);
func f = &A::set;
base_classPointer->*f();
But to be safe and sound either from the beginning make the pointer of the actual class as it seems you will be sure of that it's actually an A class.
Or use yourself of the dynamic, static, casts.
if(B * b = static_cast or dynamic_cast<B*>(mypointer))
Now I do suggest that you use yourself of exact pointer types if you are completely sure of what it's going to be. Or use yourself of the casts. If you are really anxious about performance, try the simple delegate method.
I have the following problem. I am busy coding up an inheritance structure in C++. Briefly, this is what I am attempting to do. Class A is the base class and classes B and C are inherited class. Classes B and C each have different and unique member functions.
Now, using the boost smart pointer library I make a vector of shared pointer of class type A as follows:
class A{
A();
virtual print();
}
class B : public A{
B();
virtual print();
}
class C{
C();
virtual print();
void uniqueFunc();
}
int main(){
vector<shared_ptr<A> > myA;
shared_ptr<B> myB;
shared_ptr<C> myC;
myA.push_back(myB);
myA.push_back(myC);
}
Now I have a method for checking the type of members within the vector. This isn't the issue. My question is, how do I call uniqueFunc for a member of class type C within the vector. Would I have to downcast? Or do I have to create virtual function. I do however, need uniqueFunc to be unique to class C. I would like to avoid creating copies of members and rather directly change the member in the vector.
You either need to downcast to boost::shared_ptr<C> or create a virtual function in A.
Assuming you want to downcast, you could use Boost's pointer cast functions:
boost::static_pointer_cast<C>(myA.back())->uniqueFunc();
(or use dynamic_pointer_cast<C> if you need dynamic type checking.)
Say we have a concrete class A, and an abstract class B.
Consider a concrete C, that inherits from both A and B, and implements B:
class C : public A, public B
{
/* implementation of B and specific stuff that belongs to C */
};
Now I define a function which signature is void foo(B* b);
This is my code, I can assume that every pointers to B are both A and B.
In foo's definition, how to get a pointer to A?
A nasty but working trick is to align back pointers like so:
void foo(B* b)
{
A* a = reinterpret_cast<A*>(reinterpret_cast<char*>(b) - sizeof(A));
// now I can use all the stuff from A
}
Keep in mind that C does not have a super type and actually, there are many classes akin to C which only are A and B. Feel free to question both my logic and this sample of design as well but the question is only concerning pointers alignment.
void foo(B* b)
{
//A* a = reinterpret_cast<A*>(reinterpret_cast<char*>(b) - sizeof(A)); // undefined behaviour!!!!
A* a = dynamic_cast<A*>(b);
if (a)
{
// now I can use all the stuff from A
}
else
{
// that was something else, not descended from A
}
}
Forgot to say: in order to make work dynamic cast both A and B should have virtual function(s) or at least virtual destructors. Otherwise there is no legal way to do that type conversion.
Having a huge set of unrelated classes that both derive from A and B is a very strange design. If there's something that makes A and B always be "used together" you could either merge them or introduce a shim class that only derives from them and then only derive from that class:
class Shim : A, B {};
class DerivedX : Shim {};
and in the latter case you just use static_cast to first downcast from A or B to Shim* and then C++ it will implicitly convert the Shim* pointer to the other class.
If you want to use the functionality of both class A and Class B in your function then you should modify the function to receive C pointers:
void foo(C* c);
And in general you are wrong with you assumption that "every B is an A as well". You could create classes derived from you B interface and not derived from Class A, that's why the compiler won't know that in your specific case "every B is an A".
Expanding on sharptooth's answer (and entering it as an answer, because I can't get formatted code into a comment), you can still use the shim:
class Shim : public virtual A, public virtual B {};
Then:
class Derived1 : public Shim, public virtual A, public virtual B1
{
};
class Derived2 : public Shim, public virtual A, public virtual B2
{
};
B1 and B2 must derive virtually from B.
But I suspect that if you always need to implement both A and
B, you should create a single interface with both, either by
inheriting, or coalising both into a single class; your B1 and
B2 would inherit from that. (The solution with
dynamic_cast, of course, is for the case where the derived
class of B may or may not also derived from A.)