This is something that has been frustrating me for over a week. I have gone through various threads on dynamic_casting on this website but I am still not sure what the best way to implement this is.
So I have a base class like this:
class baseClass
{
public:
class recordBase
{
public:
virtual ~recordBase(){}
};
virtual ~baseClass() {};
virtual bool Allocate( int size,
recordBase *outRecord) = 0 ;
virtual bool Free(recordBase *allocRecord) = 0;
} ;
This has two derived classes.
A derived class A like so..
class DerivedA : public baseClass
{
public:
class derivedRecordA : public baseClass::recordBase
{
public:
inline ~derivedRecordA(){} ;
someClass *obj1 ;
}
bool Allocate(int size,
baseClass::recordBase *outRecord);
bool Free(baseClass::recordBase *allocRecord) ;
}
I have a similar derived class 'DerivedB' that has its own implementation of a dervied recordBase and Allocate and Free functions.
Now Finally I have a class C that uses the above baseClass.
class C
{
public:
baseClass *allocator ;
Allocate(int size) ;
Free(void) ;
}
now here is my issue, based on some conditions class C either stores an allocator which is derivedA or stores one that is derivedB .
The allocate function for class C looks like this
C::Allocate(int size)
{
//condition where DerivedA is needed
DerivedA::derivedRecordA recObj ;
if(allocator->Allocate(size, &recObj))
{
return true;
}
else return false ;
}
Now the problem is I am forced to use dynamic casting within the DerivedA::Allocate implementation like so:
DerivedA::Allocate(int size, baseClass:recordBase *outRecord)
{
DerivedA::derivedRecordA *rec = dynamic_cast< DerivedA::derivedRecordA *>(outRecord) ;
//allocate mem and store info in 'rec'
return true ;
}
How do I avoid using dynamic_casting here. Is there a cleaner solution to this problem ?
There is a problem with your base class design which is why you are having implementation issues at the derived level.
If I have a pointer to a baseClass instance (whatever actual type it must be), then the implied contract of the Allocate method is that I can pass in a pointer to any kind of baseClass::recordBase and things should work.
If the derived classes override the function then they should not narrow the function requirements for users of the function. This would effectively mean that they are providing an override that doesn't satisfy the interface of the base class function. If they need to to this then they should provide a different function with a suitable interface.
Having said that, I would have expected an Allocate function to allocate a new object. In this case you can override and return a pointer to a specialization (this is known as a covariant return type). E.g., you can override:
virtual recordBase* Allocate(int size) = 0;
with
virtual derivedRecordA* Allocate(int size);
provided that size isn't supposed to be an array size and you are not trying to return a pointer to an array of derived objects which, again, would be problematic for users of the base class interface.
You really need to expand your question with what the contract and expected behaviour of your base class functions and there overrides are supposed to be to elicit better answers.
There is a cleaner solution, which is using a virtual function on baseRecord which is suitably overridden.
If that does not please, checking for typeid and using static_cast on success might be faster than dynamic_cast, even if it is bad coupling.
Related
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.
This may be a stupid question, I suspect I know the answer (no) because I seem to be hitting a wall here.
Given I have a collection of objects derived from certain class:
class BaseClass;
class DerivedA: public BaseClass;
class DerivedB: public BaseClass;
class DerivedC: public BaseClass;
std::vector<BaseClass> myCollection;
I want to call a method depending on the types of the specific class:
class Processor {
void doSomething(DerivedA a, DerivedB b);
void doSomething(DerivedA a, DerivedC c);
}
The problem is, if I access the individual items on the collection and try to call the 'doSomething' method in the 'Processor', it will not be able do decide which method to use (afaik). So my question is: Is there any way to fetch the items in the collection with the right derived-type?
If you are going to keep the doSomething method as it is, this is what is called multiple dispatch and is NOT currently supported by C++.
If it were a virtual member function of BaseClass then yes it would be the run of the mill C++ polymorphism on the object it is being invoked on, but it would still NOT automatically infer the type of the arguement.
To get around this you can do something like what is suggested in the earlier link
void collideWith(Thing& other) {
// dynamic_cast to a pointer type returns NULL if the cast fails
// (dynamic_cast to a reference type would throw an exception on failure)
if (Asteroid* asteroid = dynamic_cast<Asteroid*>(&other)) {
// handle Asteroid-Asteroid collision
} else if (Spaceship* spaceship = dynamic_cast<Spaceship*>(&other)) {
// handle Asteroid-Spaceship collision
} else {
// default collision handling here
}
}
Basically keep casting to various possible Derived classes until one works and call one of the methods appropriately(no special effort since the compiler knows what type you are trying to cast to).
IMPORTANT: as #WhozCraig points out, your vector needs to hold pointers to avoid Object-Slicing and render this whole question moot.
Ok, yes you should use polymorphism as the above stated. If your function needs to handle 2 objects though it gets extremely complicated.
If the derivations form a limited set and know each other you can use double-dispatch. It's not perfect but it solves this particular case.
class DerivedA;
class DerivedB;
class DerivedC;
class BaseClass
{
public:
virtual ~BaseClass();
virtual void doSomethingWithBase( BaseClass & b2 ) = 0;
virtual void doSomethingWithDerivedA( DerivedA & da ) = 0;
virtual void doSomethingWithDerivedB( DerivedB & db ) = 0;
virtual void doSomethingWithDerivedC( DerivedC & dc ) = 0;
};
class DerivedA : public BaseClass
{
public:
void doSomethingWithBase( BaseClass & b2 )
{
b2.doSomethingWithDerivedA( *this );
}
void doSomethingWithDerivedA( DerivedA & da )
{
// implement for two DerivedA objects
}
void doSomethingWithDerivedB( DerivedB & db )
{
// implement for an A and B
}
void doSomethingWithDerivedC( DerivedC & dc )
{
// implement for an A and C
}
};
// implement DerivedB to call doSomethingWithDerivedB on its parameter
// implement DerivedC to call doSomethingWithDerivedC on its parameter.
You get the idea. From where you call you don't need to know which two types you have and you never need to actually look this up. But if you ever add more implementations you have a lot of code to edit and may consider some kind of lookup table.
If you need a class to define itself you can use some kind of virtual id.
class BaseClass
{
public:
virtual int id() const = 0;
};
and then you get the classes to reveal their ids and find the handler in the table based on these ids that wil handle the two objects. The ids don't have to be ints, they can be strings which makes it easier to avoid naming clashes, and this has the advantage over the double-dispatch method of the base class not knowing its derived classes or them knowing each other, and being extensible. You also don't have to handle every pair.
Suppose I have a pure virtual method in the base interface that returns to me a list of something:
class base
{
public:
virtual std::list<something> get() = 0;
};
Suppose I have two classes that inherit the base class:
class A : public base
{
public:
std::list<something> get();
};
class B : public base
{
public:
std::list<something> get();
};
I want that only the A class can return a list<something>, but I need also to have the possibility to get the list using a base pointer, like for example:
base* base_ptr = new A();
base_ptr->get();
What I have to do?
Have I to return a pointer to this list? A reference?
Have I to return a null pointer from the method of class B? Or have I to throw an exception when I try to get the list using a B object? Or have I to change the base class method get, making it not pure and do this work in the base class?
Have I to do something else?
You have nothing else to do. The code you provide does exactly that.
When you get a pointer to the base class, since the method was declared in the base class, and is virtual, the actual implementation will be looked up in the class virtual function table and called appropriately.
So
base* base_ptr = new A();
base_ptr->get();
Will call A::get(). You should not return null from the implementation (well you can't, since null is not convertible to std::list< something > anyway). You have to provide an implementation in A/B since the base class method is declared pure virtual.
EDIT:
you cannot have only A return an std::list< something > and not B since B also inherits the base class, and the base class has a pure virtual method that must be overriden in the derived class. Inheriting from a base class is a "is-a" relationship. The only other way around I could see would be to inherit privately from the class, but that would prevent derived to base conversion.
If you really don't want B to have the get method, don't inherit from base.
Some alternatives are:
Throwing an exception in B::get():
You could throw an exception in B::get() but make sure you explain your rationale well as it is counter-intuitive. IMHO this is pretty bad design, and you risk confusing people using your base class. It is a leaky abstraction and is best avoided.
Separate interface:
You could break base into separate interface for that matter:
class IGetSomething
{
public:
virtual ~IGetSomething() {}
virtual std::list<something> Get() = 0;
};
class base
{
public:
// ...
};
class A : public base, public IGetSomething
{
public:
virtual std::list<something> Get()
{
// Implementation
return std::list<something>();
}
};
class B : public base
{
};
The multiple inheritance in that case is OK because IGetSomething is a pure interface (it does not have member variables or non-pure methods).
EDIT2:
Based on the comments it seems you want to be able to have a common interface between the two classes, yet be able to perform some operation that one implementation do, but the other doesn't provide. It is quite a convoluted scenario but we can take inspiration from COM (don't shoot me yet):
class base
{
public:
virtual ~base() {}
// ... common interface
// TODO: give me a better name
virtual IGetSomething *GetSomething() = 0;
};
class A : public Base
{
public:
virtual IGetSomething *GetSomething()
{
return NULL;
}
};
class B : public Base, public IGetSomething
{
public:
virtual IGetSomething *GetSomething()
{
// Derived-to-base conversion OK
return this;
}
};
Now what you can do is this:
base* base_ptr = new A();
IGetSomething *getSmthing = base_ptr->GetSomething();
if (getSmthing != NULL)
{
std::list<something> listOfSmthing = getSmthing->Get();
}
It is convoluted, but there are several advantages of this method:
You return public interfaces, not concrete implementation classes.
You use inheritance for what it's designed for.
It is hard to use mistakenly: base does not provide std::list get() because it is not a common operation between the concrete implementation.
You are explicit about the semantics of GetSomething(): it allows you to return an interface that can be use to retrieve a list of something.
What about just returning an empty std::list ?
That would be possible but bad design, it's like having a vending machine that can give Coke and Pepsi, except it never serves Pepsi; it's misleading and best avoided.
What about just returning a boost::optional< std::list< something > > ? (as suggested by Andrew)
I think that's a better solution, better than returning and interface that sometimes could be NULL and sometimes not, because then you explicitly know that it's optional, and there would be no mistake about it.
The downside is that it puts boost inside your interface, which I prefer to avoid (it's up to me to use boost, but clients of the interface shouldn't have to be forced to use boost).
return boost::optional in case you need an ability to not return (in B class)
class base
{
public:
virtual boost::optional<std::list<something> > get() = 0;
};
What you are doing is wrong. If it is not common to both the derived classes, you should probably not have it in the base class.
That aside, there is no way to achieve what you want. You have to implement the method in B also - which is precisely the meaning of a pure virtual function. However, you can add a special fail case - such as returning an empty list, or a list with one element containing a predetermined invalid value.
I have a function like this:
void something(void *obj)
{
obj->Set();
}
The compiler says that left of the dereference operator has to be a pointer to a class/struct/union/generic (translated from german not sure about wording).
The idea is that I want to call the something function of obj no matter what is passed to something. It is ensured that it has this function. How can i achieve that?
--EDIT--
I started to work on an existing Software which has like > 100 Classes for datatypes. In one part of the code there is a big switch statement which depending on an id creates an instance of one of these classes and calls the Set function for that one. Now i want to do multiple of these calls parallel, and because of this i want to bring the ->Set() call to a seperate function which i then can call in a new thread. Sadly there is no baseclass and i cant change too much in the "big picture". What is the best way to do this?
C++ doesn’t allow this (for good reasons: even if you can ensure that the object always has a function, C++ cannot, and since you can make mistakes, C++ is justified in distrusting you).
The proper way to do this is to have a common base class which defined this method for all types that you want to use here, and then use this common base class as the argument of this function.
Alternatively, if it’s known at compile time which type is used here, then the appropriate implementation uses templates:
template <typename T>
void f(T const& obj) {
obj.something();
}
Whatever you do, void* is not appropriate. There are very rare legitimate use-cases for it in C++.
You need a base class or interface for whatever is passed into doSth:
class Base
{
public:
virtual void something() = 0; //override this in derived classes
}
doSth(Base* obj)
{
obj->something();
}
You can also cast the void* back to the original type:
doSth(void* obj)
{
((Base*)obj)->something();
}
but passing a void* as parameter suggests a faulty design. What exactly are you trying to achieve?
You need to implement pure virtual Base class with this function:
class Base
{
public:
virtual ~Base(){}
virtual void somefunction()=0;
}
class Derived1: public Base
{
public:
void somefunction()
{
//do something
}
}
class Derived2: public Base
{
public:
void somefunction()
{
//do something
}
}
And than use dynmic cast to get Base* from void*
doSth(void *obj)
{
Base *bobj=dynamic_cast<Base*>(obj);
if ( bobj )
bobj->somefunction();
}
Or mor simplier:
doSth(Base *obj)
{
obj->somefunction();
}
And usage is like:
Base *p1 = new Derived1();
Base *p2 = new Derived2();
doSth(p1); // cals somefunction in Derived1 class
doSth(p2); // cals somefunction in Derived2 class
The doSth method could take a function pointer as a parameter.
doSth( (*someFunc)() ) {
obj->*someFunc();
}
The call would look like:
doSth( &function );
When passing function pointers between different classes you should create a typedef for each function pointer and use qualifiers for each function identifier.
Just define an interface that lists all the functions of all the objects that you want to reference by the pointer, but the type of this pointer should not be void, but the name of this interface instead.
Then you will be able to call every function of every object that you want by this pointer, but make sure that all structures and classes of the objects implement all the functions of the interface!
This is also important to write the : public and then the name of the interface in the header of every structure and class!
I have a vector with pointers of type Vehicle. Vehicle is the base class and there are many derived types like MotorCycle, Car, Plane, etc. Now, in my program there comes a point where I need the derived type while traversing the vector. Each Vehicle class has a GetType() function which returns an int which tells me what the derived type is (motorcylce, car, plan). So, I can use a dynamic cast to downcast to the derived type from the base class pointer. However, I need to have a giant if statement everytime I need the derived pointer
if(vehicle_ptr->GetType() == PLANE)
Plane *ptr = dynamic_cast<Plane*> vehicle_ptr;
else if (vehicle_ptr->GetType() == MOTORCYCLE)
MotorCycle *ptr = dynamic_cast<MotorCycle*> vehicle_ptr;
..and on and on.
Is there a way to have a function or some trick I can call that would save me from the giant if statement everywhere? Like ::GetDerivedPtr(Vehicle *ptr). Would a template class help here? (never used them before) Sorry, my C++ is a bit rusty and I did search but these terms bring up too much material to find what I'm looking for. Thanks.
It looks like you've manually tried to recreate polymorphism. You don't need a type member. This is almost always a bad idea. Use polymorphism and virtual functions.
When you have a vehicle pointer v and do
v->function();
It will call the proper function for whatever type (Plane, Train, or Automobile) that the pointer actually points to if function is a virtual function. What you're doing is already handled by the language.
So:
class A {
public:
virtual void f() {cout << "A";}
};
class B : public A {
public:
virtual void f() {cout << "B";}
};
int main(){
A *a;
B b;
a = &b;
a->f();
}
The above snippet will print B.
I second the idea that you need some virtual function and a common base type. Imagine that there is some way to get the pointer which has the correct type. What will you do with it then? You'll have to make a giant switch anyway, because you call specific functions for each of your specific types.
One solution would be to invent a name for the operation you are trying to execute, and put its implementation as a virtual function at each specific Vehicle class. If the operation accepts different parameter for each of the cases, the parameters have to be packed into a special polymorphic structure/class, but here maybe the Visitor pattern is a more generic solution.
First check whether what you're going to do can be done simply via virtual functions in class Vehicle, overridden by each derived class.
If not, then consider the Visitor Pattern.
Cheers & hth.,
dynamic_cast will check the type itself (you don't need your own variable for this). You can do the following instead:
Plane *plane_ptr = dynamic_cast<Plane*>(vehicle_ptr);
if(plane_ptr != NULL)
{
// Do stuff with 'plane_ptr' that you couldn't do with 'vehicle_ptr'
}
I don't really see how creating a function to do the cast would help because you still need to class specific code anyway (and the function would have a fixed return type, so the closest you could get is something like the 'dynamic_cast' call, which is pretty much a standard function anyway).
Use Visitor based dispatching. Observe that not a simple cast of any kind is required in the follwing (somewhat trivialized) example:
// simple cyclic visitor
class VehicleVistor {
public:
// add overload for each concrete Vehicle type
virtual void Visit(class Motorcycle&) {};
virtual void Visit(class Plane&) {};
virtual void Visit(class Car&) {};
};
class Vehicle {
public:
virtual Accept(VehicleVisitor&) = 0;
};
class Car : public Vehicle {
public:
virtual Accept(VehicleVisitor& pVisitor) {
pVisitor.Visit(*this);
}
};
// and so on...
At some point of you program you need to retrieve all instances of, say Motorcycle:
class MotorcycleExtractingVisitor : public VehicleVisitor {
std::vector<Motorcycle*> mMotorcycles;
public:
void operator()(Vehicle* pVehicle) {
pVehicle->Accept(*this);
}
void Visit(Motorcycle& pMotorcycle) {
mAllMotorcycles.push_back(pMotorcycle);
}
std::vector<Motorcycles*> Get() { return mAllMotorcycles; }
};
class Extractor {
public:
// here you extract motorcycles
static std::vector<Motorcycle*> ExtractMotorcycles(std::vector<Vehicle*>& pVehicles) {
MotorcycleExtractingVisitor tMotos;
std::for_each(pVehicles.begin(), pVehicles.end(), tMotos);
return tMotos.Get();
}
// this would be a templatized version, left as exercise to the reader
template<class TExtracted, classtypename TBegItr, typename TEndItr>
static std::vector<TExtracted*> Extract(TBegItr pBeg, TEndItr pEnd) {
ExtractingVisitor<TExtracted> tRequiredVehicles;
std::for_each(pBeg, pEnd, tRequiredVehicles);
return tRequiredVehicles.Get();
}
};
Usage is as follows:
// fixed type version:
std::vector<Motorcycles*> tMotos =
Extractor::Extract(tVehicleVector);
// templatized version (recommended)
std::vector<Motorcycles*> tMotos =
Extractor::Extract<Motorcycles>(
tVehicleVector.begin(),tVehicleVector.end());