C++ checking the type of reference - c++

Is it bad design to check if an object is of a particular type by having some sort of ID data member in it?
class A
{
private:
bool isStub;
public:
A(bool isStubVal):isStub(isStubVal){}
bool isStub(){return isStub;}
};
class A1:public A
{
public:
A1():A(false){}
};
class AStub:public A
{
public:
AStub():A(true){}
};
EDIT 1:
Problem is A holds a lot of virtual functions, which A1 doesn't override but the stub needs to, for indidicating that you are working on a stub instead of an actual object. Here maintainability is the question, for every function that i add to A, i need to override it in stub. forgetting it means dangerous behaviour as A's virtual function gets executed with stub's data. Sure I can add an abstract class ABase and let A and Astub inherit from them. But the design has become rigid enough to allow this refactor.
A reference holder to A is held in another class B. B is initialized with the stub reference, but later depending on some conditions, the reference holder in B is reinitialized with the A1,A2 etc.. So when i do this BObj.GetA(), i can check in GetA() if the refholder is holding a stub and then give an error in that case. Not doing that check means, i would have to override all functions of A in AStub with the appropriate error conditions.

Generally, yes. You're half OO, half procedural.
What are you going to do once you determine the object type? You probably should put that behavior in the object itself (perhaps in a virtual function), and have different derived classes implement that behavior differently. Then you have no reason to check the object type at all.
In your specific example you have a "stub" class. Instead of doing...
if(!stub)
{
dosomething;
}
Just call
object->DoSomething();
and have the implemention in AStub be a empty

Generally yes. Usually you want not to query the object, but to expect it to BEHAVE the proper way. What you suggest is basically a primitive RTTI, and this is generally frowned upon, unless there are better options.
The OO way would be to Stub the functionality, not check for it. However, in the case of a lot of functions to "stub" this may not seem optimal.
Hence, this depends on what you want the class to really do.
Also note, that in this case you don't waste space:
class A
{
public:
virtual bool isStub() = 0;
};
class A1:public A
{
public:
virtual bool isStub() { return false; };
};
class AStub:public A
{
public:
virtual bool isStub() { return true; };
};
... buuut you have a virtual function -- what usually is not a problem, unless it's a performance bottleneck.

If you want to find out the type of object at runtime you can use a dynamic_cast. You must have a pointer or reference to the object, and then check the result of the dynamic_cast. If it is not NULL, then the object is the correct type.

With polymorphic classes you can use the typeofoperator to perform RTTI. Most of the time you shouldn't need to. Without polymorphism, there's no language facility to do so, but you should need to even less often.

One caveat. Obviously your type is going to be determined at construction time. If your determination of 'type' is a dynamic quantity you can't solve this problem with the C++ type system. In that case you need to have some function. But in this case it is better to use the overridable/dynamic behavior as Terry suggested.
Can you provide some better information as what you are trying to accomplish?

This sort of thing is fine. It's generally better to put functionality in the object, so that there's no need to switch on type -- this makes the calling code simpler and localises future changes -- but there's a lot to be said for being able to check the types.
There will always be exceptions to the general case, even with the best will in the world, and being able to quickly check for the odd specific case can make the difference between having something fixed by one change in one place, a quick project-specific hack in the project-specific code, and having to make more invasive, wide-reaching changes (extra functions in the base class at the very least) -- possibly pushing project-specific concerns into shared or framework code.
For a quick solution to the problem, use dynamic_cast. As others have noted, this lets one check that an object is of a given type -- or a type derived from that (an improvement over the straightforward "check IDs" approach). For example:
bool IsStub( const A &a ) {
return bool( dynamic_cast< const AStub * >( &a ) );
}
This requires no setup, and without any effort on one's part the results will be correct. It is also template-friendly in a very straightforward and obvious manner.
Two other approaches may also suit.
If the set of derived types is fixed, or there are a set of derived types that get commonly used, one might have some functions on the base class that will perform the cast. The base class implementations return NULL:
class A {
virtual AStub *AsStub() { return NULL; }
virtual OtherDerivedClass *AsOtherDerivedClass() { return NULL; }
};
Then override as appropriate, for example:
class AStub : public A {
AStub *AsStub() { return this; }
};
Again, this allows one to have objects of a derived type treated as if they were their base type -- or not, if that would be preferable. A further advantage of this is that one need not necessarily return this, but could return a pointer to some other object (a member variable perhaps). This allows a given derived class to provide multiple views of itself, or perhaps change its role at runtime.
This approach is not especially template friendly, though. It would require a bit of work, with the result either being a bit more verbose or using constructs with which not everybody is familiar.
Another approach is to reify the object type. Have an actual object that represents the type, that can be retrieved by both a virtual function and a static function. For simple type checking, this is not much better than dynamic_cast, but the cost is more predictable across a wide range of compilers, and the opportunities for storing useful data (proper class name, reflection information, navigable class hierarchy information, etc.) are much greater.
This requires a bit of infrastructure (a couple of macros, at least) to make it easy to add the virtual functions and maintain the hierarchy data, but it provides good results. Even if this is only used to store class names that are guaranteed to be useful, and to check for types, it'll pay for itself.
With all this in place, checking for a particular type of object might then go something like this example:
bool IsStub( const A &a ) {
return a.GetObjectType().IsDerivedFrom( AStub::GetClassType() );
}
(IsDerivedFrom might be table-driven, or it could simply loop through the hierarchy data. Either of these may or may not be more efficient than dynamic_cast, but the approximate runtime cost is at least predictable.)
As with dynamic_cast, this approach is also obviously amenable to automation with templates.

In the general case it might not be a good design, but in some specific cases it is a reasonable design choice to provide an isStub() method for the use of a specific client that would otherwise need to use RTTI. One such case is lazy loading:
class LoadingProxy : IInterface
{
private:
IInterface m_delegate;
IInterface loadDelegate();
public:
LoadingProxy(IInterface delegate) : m_delegate(delegate){}
int useMe()
{
if (m_delegate.isStub())
{
m_delegate = loadDelegate();
}
return m_delegate.useMe();
}
};
The problem with RTTI is that it is relatively expensive (slow) compared with a virtual method call, so that if your useMe() function is simple/quick, RTTI determines the performance. On one application that I worked on, using RTTI tests to determine if lazy loading was needed was one of the performance bottlenecks identified by profiling.
However, as many other answers have said, the application code should not need to worry about whether it has a stub or a usable instance. The test should be in one place/layer in the application. Unless you might need multiple LoadingProxy implementations there might be a case for making isStub() a friend function.

Related

Should I make a class polymorphic if only one of its methods should behave differently depending on the object's data type?

I have a class Group containing a vector of objects of another class Entry. Inside the Group I need to frequently access the elements of this vector(either consequently and in random order). The Entry class can represent a data of two different types with the same properties(size, content, creation time etc.). So all of the members and methods of the Entry class are the same for both data types, except for one method, that should behave differently depending on the type of the data. It looks like this:
class Entry
{
public:
// ...
void someMethod();
// ...
private:
TYPE type_;
// ...
};
class Group
{
private:
// ...
std::vector<Entry> entries_;
// ...
};
void Entry::someMethod()
{
if (type_ == certainType)
{
// Do some stuff
}
else if (type_ == anotherType)
{
// Do some different stuff
}
}
Given the abilities of C++ regarding OOP, this approach seems unnatural to me. I am thinking about creation of two distinct classes inherited from the Entry class and overriding only this someMethod() in those classes:
class Entry
{
// ...
virtual void someMethod() = 0;
// ...
};
class EntryType1 : public Entry
{
// override someMethod() here
};
class EntryType2 : public Entry
{
// override someMethod() here
};
But doing so means reducing the efficiency of cache usage, because now inside the Group class I have to replace the vector of Entry objects placed in a contiguous memory area with the vector of pointers to Entry base class objects scattered all over the memory address space.
The question is - is it worth it to make a class polymorphic just because of one only among many other of its methods is needed to behave differently depending on the data type? Is there any better approach?
is it worth it to make a class polymorphic just because of one only among many other of its method is needed to behave differently depending on the data type?
Runtime polymorphism starts to provide undeniable net value when the class hierarchy is deep, or may grow arbitrarily in future. So, if this code is just used in the private implementation of a small library you're writing, start with what's more efficient if you have real reason to care about efficiency (type_ and if), then it's not much work to change it later anyway. If lots of client code may start to depend your choices here though, making it difficult to change later, and there's some prospect of further versions of someMethod() being needed, it's probably better to start with the virtual dispatch approach.
Is there any better approach?
Again - what's "better" takes shape at scale and depends on how the code is depended upon, updated etc.. Other possible approaches include using a std::variant<EntryType1, EntryType2>, or even a std::any object, function pointers....
If you are absolutely sure that there are only two types of Entry, then using an if inside the function's implementation is, to me, a perfectly valid approach. In this case, I would advise you to use if constexpr to further indicate that this is a compile-time behavioral decision and not a runtime one. (As pointed out by Tony Delroy, if constexpr is not viable).
If, however, you are unsure if you are going to need more Entry types in the future, the if approach would only hurt you in the long run. If you need the scalability, I would advise you to make the Entry class hold a std::function internally for only that specific behavior that needs polymorphism: this way you're only paying for indirection when you actually need the functionality.
You could also make two factory functions make_Entry1 and make_Entry2 that construct an Entry passing it the specific std::function that yields the desired behavior.

Typesafe method for retrieving data of unknown type through interface

TL;DR version:
I am designing a class in C++14 to be generic. Below I describe a design problem, and I would be grateful for a solution to implement what I'm trying, or a suggestion for a redesign.
Say the class I'm designing is called Algo. Its constructor is passed a unique_ptr to a type, say Business, which implements an interface (i.e., inherits from a pure virtual class) and does most of the serious work.
I want an object of type Algo to be able to return a pointer (or even a copy) of a data member from the Business object that it owns. But it can't know the type that Business will want to return. I expect the owner of Algo to know what will come out based on what Business he passed in.
In my C days, I would blow off the type system by passing around void* and casting as needed. But that sort of thing now wreaks to me.
More detail:
So, a sort of pseudo-C++14 implementation of the above situation might look like:
// perhaps a template here?
class AbstractBusiness {
. . .
public:
?unknownType? result();
};
class Algo {
//Could be public if needbe.
unique_ptr<AbstractBusiness> concreteBusiness_;
public:
Algo(std::unique_ptr<AbstractBusiness> concreteBusiness);
auto result() {return concreteBusiness_.result();}
};
class Business : public AbstractBusiness {
. . .
public:
std::valarray<float> data_;
std::valarray<float> result() {return data_;}
};
:::
auto b = std::unique_ptr<AbstractBusiness>{std::move(new Business())};
Algo a(std::move(b));
auto myResult = a.result();
In this example, myResult will be a std::valarray<float>, but I don't want Algo or the AbstractBusiness interface to have to know that! The creator of b and a should be in charge of knowing what should come out of a.result().
If I am taking a wrong turn in this design, don't hesitate to let me know. I'm a bit green at this point and very open to suggestions.
I've tried...
I obviously can't use auto for a virtual method, nor have a template in a virtual class. These are the only things that stood out.
I'm playing with the idea of making a container interface for whatever Business.result() returns, and just passing pointers to abstract type up to Algo.result(). But I'm starting to feel like there may be a better way, so I'm on here begging for suggestions.
You haven't actually described a design problem. You've described some
implementation choices that you've gone with and a roadblock you've
run into, but we don't know the reasons for the choices.
You tell us that Algo takes ownership of a business via a pointer to a
polymorphic interface AbstractBusiness and must provide a getter for
that business's data, though it doesn't know the concrete type of that
data (because it doesn't know the concrete type of the business).
Neither of these questions have evident answers:-
Why should Algo acquire a business via a polymorphic interface?
Why should Algo provide a getter for the data of its business?
But deciding it must be so leads to the roadblock.
The polymorphic pothole and how to get out it
Q1. leads us to wonder what is the motivation for AbstractBusiness? Platitudinously, it's safe to say you want it to provide a uniform interface for manipulating and querying all sorts of businesses of concrete types that may be determined at runtime.
To be fully fit for that purpose, AbstractBusiness will encapsulate a necessary and sufficient interface for discharging all of the operations and queries on concrete businesses that applications (including but not limited to your own) can reasonably be expected to need. Call that Plan A. What you have discovered is that it isn't fully fit for Plan A. If the application needs at times to manipulate or query "the data" of a business that is represented to it via an AbstractBusiness, then the AbstractBusiness interface needs to provide polymorphic methods to discharge all of those manipulations and queries, and each concrete business class needs to implement them appropriately for the type of data it contains.
Where your AbstractBusiness has the problematic:
?unknownType? result();
you need to code virtual methods that address all of the convincing answers to the question: What might an application want to know about the notional result() , or do to it?
In this light, the suggestion that has been canvassed to introduce another polymorphic interface, AbstractData, ancestral to all of the concrete data types of all the concrete businesses, may be viewed as a suggestion to compensate for the necessary methods that are missing from AbstractBusiness by separately encapsulating them in a rescue abstraction. Better to finish the unfinished AbstractBusiness.
This is all good and scriptural perhaps, but maybe what has actually stopped you from finishing AbstractBusiness already is the perception that the data of BusinessX can be essentially different from that of BusinessY, so that it is impossible to devise a single set of polymorphic methods that is necessary and sufficient to manage both.
If this is the case, it tells you that businesses cannot all be managed through a single abstract interface. AbstractBusiness can't be fully fit for that purpose and, if it has a role, its role can only be to manage polymorphic objects that represent more specialized abstractions, BusinessTypeX, BusinessTypeY, etc., within each of which the variety, if any, of concrete types can be accommodated by a single polymorphic interface.
AbstractBusiness will then present only the interface that is shared
by all businesses. It will have no result() at all and a caller who obtains a pointer to AbstractBusiness with the intention of doing something with
with the thing returned by BusinessTypeX::result() will proceed by dynamically casting the source pointer to BusinessTypeX *, and calling result() through the target pointer only if its not null.
We still do not know what is the motivation of AbstractBusiness. We've just pursued the fairly plausible thought that you have "textbook" ambitions for it - Plan A - and have either failed to realize that you just haven't finished it, or you have grasped that the diversity of the data you're dealing with prevents you from finishing it per Plan A, and don't have a Plan B. Plan B is: Deepen the polymorphic hierarchy and use dynamic_cast<LowerType *>(HigherType *) to secure safe access to the LowerType interface when it outruns the HigherType one. [1]
The turn of Q2. now. Most likely, the reason for Algo::result() is simply: Because it's the done thing for a class to provide getters that directly
answer the client's natural queries, and in this case a natural query is for the data owned by the business that is owned by the Algo. But if the Algo knows its business only as an AbstractBusiness, then it just can't return the data owned by its business, because the reasons already seen mean that AbstractBusiness can't return "the data" to the Algo, or to anything else.
Algo::result() is misconceived identically as AbstractBusiness::result() is misconceived. Given that BusinessXs data and BusinessYs data might need to be queried either through some repertoire of virtual methods that are still TODO in AbstractBusiness (Plan A), or perhaps through methods of BusinessX and BusinessY that are not inherited from AbstractBusiness at all (Plan B), the only query that Algo certainly can and should support with respect to its business is to return the AbstractBusiness pointer
through which it owns its business, leaving it to the caller to query through the pointer or downcast it, if they can, to a lower-type interface they want query. Even if it is possible to finish AbstractBusiness per Plan A, the idea that the missing reportoire of methods should all be duplicated in the interface of Algo just so that a caller never has to receive and downcast an AbstractBusiness pointer is uncompelling. Would every type that manages an AbstractBusiness pointer follow suit?
Summarizing thus far, if AbstractBusiness has a good reason to exist, then you need either to finish it per Plan A, and work through the repercussions of so doing, or else curtail it short of attempting to be a sufficient interface for managing all businesses and bolster it with an enriched polymorphic hierarchy that clients negotiate by dynamic casting, per Plan B; and in either case you should be content for Algo and similar jobsworths in the AbstractBusiness trade just to return their AbstractBusiness pointer to clients who have specialized uses for it.
Better than that, don't go there
But the question of whether AbstractBusiness has a good reason to exist is still dangling, and should you find yourself driven to Plan B that in itself will make the question more pointed: when it transpires that an abstract interface, cast as the root class of a single inheritance hierarchy, cannot deliver Plan A then a doubt arises about the wisdom of the architecture it figures it. Dynamic casting to detect and acquire interfaces is a clunky and expensive mode of flow control and especially vexatious when - as you tell us is your situation - a scope that will have to perform the downcasting rigmarole already knows the type it should "get out" is the type it "put in". Do all the types that are imperfectly descended from the root abstraction need to have a single ancestor, for a reason other than uniformity of interface (since it doesn't give them that)? The economies of generic interfaces are an ever-present goal, but is runtime polymorphism
the right means, or even one of the right means, to realize them in the context of your project?
In your code-sketch, AbstractBusiness serves no end purpose but to furnish a
type that can uniformly fill certain slots in class Algo, with the effect that Algo can operate correctly on any type that exhibits certain traits and
behaviours. As sketched, Algos only requirement of a qualifying type is
that it shall have a result() method that returns something: it doesn't care what. But the fact that you express Algos requirements upon a qualifying type by specifying that it shall be an AbstractBusiness prohibits it from not caring what is returned by result(): AbstractBusiness cannot do that result() method, although any of its descendants might do.
Suppose in that case that you sack AbstractBusiness from the job of enforcing the generic attributes of types on which Algo can operate and let Algo itself do that instead, by making it a template? - since it looks as if what AbstractBusiness is doing for Algo is serving the purpose of a template parameter but sabotaging that very purpose:
#include <memory>
template<class T>
class Algo {
std::unique_ptr<T> concreteBusiness_;
public:
explicit Algo(T * concreteBusiness)
: concreteBusiness_{concreteBusiness}{};
auto result() { return concreteBusiness_->result(); }
};
#include <valarray>
#include <algorithm>
struct MathBusiness {
std::valarray<float> data_{1.1,2.2,3.3};
float result() const {
return std::accumulate(std::begin(data_),std::end(data_),0.0);
}
};
#include <string>
struct StringBusiness {
std::string data_{"Hello World"};
std::string result() const { return data_; }
};
#include <iostream>
int main()
{
Algo<MathBusiness> am{new MathBusiness};
auto ram = am.result();
Algo<StringBusiness> as{new StringBusiness};
auto ras = as.result();
std::cout << ram << '\n' << ras << '\n';
return 0;
}
You see that in this way of transferring the genericity from AbstractBusiness to Algo, the former is left completely redundant, and so removed. This is a nutshell illustration of how the introduction of templates changed the game of C++ design root and branch, making polymporhic designs obselete for most of their prior applications to the crafting of generic interfaces.
We are working from a sketch of your problem context: perhaps there remain good reasons not in sight for AbstractBusiness to exist. But even if there are, they don't per se constitute reasons for Algo not to be a template or to have any dependency on AbstractBusiness. And perhaps they can one by one be eliminated by similar treatments.
Making Algo into a template still might not be a viable solution for you, but if it isn't then there is essentially more to the problem than we have seen. And anyhow take away this rule of thumb: Templates for generic interfaces; polymorphism for runtime adaptation of an interface's behaviour.
[1] What might look like another plan is to encapulate "the data" of each concrete
business in a boost::any or std::experimental::any. But you can probably
see straightaway that this is essentially the same as the idea of encapsulating
the data in a rescue abstraction, using an off-the shelf Swiss Army abstraction,
rather than crafting your own. In either guise, the idea still leaves
callers to downcast the abstraction to the type of real interest to find out
if that's what they've got, and in that sense is a variant of Plan B.
There are several ways to go at this. The easiest way is to not pass the ownership but call Algo by reference:
Business b;
Algo(b);
auto result = b.get_result();
However, sometimes this is not possible. In that case various options open up that can become quite complicated. Let me start with the most versatile and complicated one:
If you know all the types that derive from AbstractBusiness you could use the visitor pattern:
First we declare an abstract method accept in AbstractBusiness that takes a BusinessVisitor. This visitor will be responsible to handle the different types and perform an action based on which type it is visiting:
class BusinessVisitor;
struct AbstractBusiness {
virtual ~AbstractBusiness() = default;
virtual void accept(BusinessVisitor&) const = 0;
};
The BusinessVisitor looks like this:
class BusinessOne;
class BusinessTwo;
struct BusinessVisitor {
virtual ~BusinessVisitor() = default;
virtual void on_business_one(const BusinessOne&) {};
virtual void on_business_two(const BusinessTwo&) {};
};
Some people prefer to call all methods in the visitor visit and let overload resolution do the rest but I prefer more explicit names.
struct BusinessOne {
void accept(BusinessVisitor& v) const {
v.on_business_one(*this);
}
};
struct BusinessTwo {
void accept(BusinessVisitor& v) const override {
v.on_business_two(*this);
}
};
Now we can add an accept method to Algo as well. This one will simply dispatch to the contained AbstractBusiness object.
class Algo {
std::unique_ptr<AbstractBusiness> b_;
public:
Algo(std::unique_ptr<AbstractBusiness> b);
void accept(BusinessVisitor& visitor) const override {
return b_->accept(visitor);
}
};
To get the result for a specific business type we need to define a visitor that handles this type:
struct BusinessOneResult : public BusinessVisitor {
void on_business_one(const BusinessOne& b) {
// save result;
}
/* ... */ get_result() const;
};
Now we can run Algo and retrieve the result:
auto b = std::unique_ptr<AbstractBusiness>(new BusinessOne());
Algo a(std::move(b));
BusinessOneResult visitor;
a.accept(visitor);
auto result = visitor.get_result();
The real power of this approach unfolds if you don't want extract a specific value from Algo but if you want to trigger an action. In that case the action is usually different depending on the business type, thus the whole action can be specified in the visitor.
A different and quite elegant way would be to use a std::future:
struct Business {
std::future</*...*/> get_future_result() {
return promise_.get_future();
}
void some_method() {
// ...
promise_.set_value(...);
}
private:
std::promise</*...*/> promise_;
};
// Must use Business here (AbstractBusiness doesn't know about the
// type of the future).
auto b = std::unique_ptr<Business>(new Business());
auto future = b.get_future_result();
Algo a(std::move(b));
auto result = future.get();
Another way would be to wrap the type in a class derived from a tag class (no methods or data members) and dynamic_cast it to the type you know it contains. Using dynamic_cast it's usually frowned upon but it has it's uses.
std::any or boost::any would be another way to go.
Note: I dropped the std::move for the argument of the std::unique_ptr constructor, it doesn't do a thing there: The result of the new operation is already an rvalue and moving a pointer is as efficient as copying it.

C++ Design issues: Map with various abstract base classes

I'm facing design problems and could do with some external input. I am trying to avoid abstract base class casting (Since I've heard that's bad).
The issues are down to this structure:
class entity... (base with pure virtual functions)
class hostile : public entity... (base with pure virtual functions)
class friendly : public entity... (base with pure virtual functions)
// Then further derived classes using these last base classes...
Initially I thought I'd get away with:
const enum class FactionType : unsigned int
{ ... };
std::unordered_map<FactionType, std::vector<std::unique_ptr<CEntity>>> m_entitys;
And... I did but this causes me problems because I need to access "unique" function from say hostile or friendly specifically.
I have disgracefully tried (worked but don't like it nor does it feel safe):
// For-Each Loop: const auto& friendly : m_entitys[FactionType::FRIENDLY]
CFriendly* castFriendly = static_cast<CFriendly*>(&*friendly);
I was hoping/trying to maintain the unordered_map design that uses FactionType as a key for the base abstract class type... Anyway, input is greatly appreciated.
If there are any syntactical errors, I apologise.
About casting I agree with with #rufflewind. The casts mean different thing and are useful at different times.
To coerce a region of memory at compile time (the decision of typing happen at compile time anyway) use static_cast. The amount of memory on the other end of the T* equal to sizeof(T) will be interpreted as a T regardless of correct behavior.
The decisions for dynamic_cast are made entirely at runtime, sometimes requiring RTTI (Run Time Type Information). It makes a decision and it will either return a null pointer or a valid pointer to a T if one can be made.
The decision goes further than just the types of casts though. Using a data structure to look up types and methods (member functions) imposes the time constraints that would not otherwise exist when compared to the relatively fast and mandatory casts. There is a way to skip the data structures, but not the casting without major refactoring (with major refactoring you can do anything).
You can move the casts into the entity class, get them done right and just leave them encapsulated there.
class entity
{
// Previous code
public:
// This will be overridden in hostiles to return a valid
// pointer and nullptr or 0 in other types of entities
virtual hostile* cast_to_hostile() = 0
virtual const hostile* cast_to_hostile() const = 0
// This will be overridden in friendlies to return a valid
// pointer and nullptr or 0 in other types of entities
virtual friendly* cast_to_friendly() = 0
virtual const friendly* cast_to_friendly() const = 0
// The following helper methods are optional but
// can make it easier to write streamlined code in
// calling classes with a little trouble.
// Hostile and friendly can each implement this to return
// The appropriate enum member. This would useful for making
// decision about friendlies and hostiles
virtual FactionType entity_type() const = 0;
// These two method delegate storage of the knowledge
// of hostility or friendliness to the derived classes.
// These are implemented here as non-virtual functions
// because they shouldn't need to be overridden, but
// could be made virtual at the cost of a pointer
// indirection and sometimes, but not often a cache miss.
bool is_friendly() const
{
return entity_type() == FactionType_friendly;
}
bool is_hostile() const
{
return entity_type() == FactionType_hostile;
}
}
This strategy is good and bad for a variety of reasons.
Pros:
It is conceptually simple. This is easy to understand quickly if you understand polymorphism.
It seems similar to your existing code seems superficially similar to your existing code making migration easier. There is a reason hostility and friendliness is encoded in your types, this preserves that reason.
You can use static_casts safely because all the casts exist in the class they are used in, and therefor won't normally get called unless valid.
You can return shared_ptr or other custom smart pointers instead of raw pointers. And you probably should.
This avoids a potentially costly refactor that completely avoids casting. Casting is there to be used as a tool.
Cons:
It is conceptually simple. This does not provide a strong set of vocabulary (methods, classes and patterns) for building a smart set of tools for building advanced type mechanics.
Likely whether or not something is hostile should be a data member or implemented as series of methods controlling instance behavior.
Someone might think that the pointers this returns convey ownership and delete them.
Every caller must check pointers for validity prior to use. Or you can add methods to check, but then callers will need to call methods to check before the cast. Checks like these are surprising for users of the class and make it harder to use correctly.
It is polymorphism dense. This will perplex people who are uncomfortable with polymorphism. Even today there are many who are not comfortable with polymorphism.
A refactor that completely avoids casting is possible. Casting is dangerous and not a tool to use lightly.

Alternate ways to identify polymorphic objects?

I've been searching all through the web and I seem to not find any alternate way of doing comparing if two polymorphic objects are the same type, or if a polymorphic object IS a type. The reason for this is because I am going to implement a Entity System inside of my game that I am currently creating.
I have not found another way of doing this other than with the use macros or a cast (the cast not being a portable method of doing so). Currently this is how I am identifying objects, is there a more efficient or effective way of doing this? (without the use of C++ RTTI)
I pasted it on pastebin, since pasting it here is just too much of a hassle.
http://pastebin.com/2uwrb4y2
And just incase you still do not understand exactly what I'm trying to achieve, I'll try to explain it. An entity in a game is like an object inside of the game (e.g. a player or enemy), it have have components attached to it, these components are data for an entity. A system in the entity system is what brings the data and logic of the game together.
For example, if I wanted to display a model up on the screen it would be similar to this:
World world; // Where all entities are contained
// create an entity from the world, and add
// some geometry that is loaded from a file
Entity* e = world.createEntity();
e->add(new GeometryComponent());
e->get<GeometryComponent>()->loadModel("my_model.obj"); // this is what I want to be able to do
world.addSystem(new RenderingSystem());
// game loop
bool isRunning = true;
while(isRunning)
{
pollInput();
// etc...
// update the world
world.update();
}
EDIT:
Here's a framework, programmed in Java, that does mainly what I want to be able to do.
http://gamadu.com/artemis/tutorial.html
See std::is_polymorphic. I believe boost has it too.
If T is a polymorphic class (that is, a class that declares or inherits at least one virtual function), provides the member constant value equal true. For any other type, value is false.
http://en.cppreference.com/w/cpp/types/is_polymorphic
Edit:
Why can't you just do this in your example?
Entity* e = world.createEntity();
GemoetryComponent* gc = new GeometryComponent();
gc->loadModel("my_model.obj");
e->add(gc);
Create the structure before stripping the type information.
If you're determined not to use C++'s built-in RTTI, you can reimplement it yourself by deriving all classes from a base class that contains a virtual method:
class Base {
public:
virtual string getType() = 0;
};
Then every derived class needs to overload this method with a version that returns a distinct string:
class Foo : public Base {
public:
string getType() { return "Foo"; }
};
You can then simply compare the results of calling getType() on each object to determined if they are the same type. You could use an enumeration instead of a string if you know up front all the derived classes that will ever be created.
Entity* e = world.createEntity();
e->add(new GeometryComponent());
e->get<GeometryComponent>()->loadModel("my_model.obj");
// this is what I want to be able to do
First the simple: there is a base type to all of the components that can be added, or else you would not be able to do e->add(new GeometryComponent()). I assume that this particular base has at least one virtual function, in which case the trivial solution is to implement get as:
template <typename T>
T* get() {
return dynamic_cast<T*>(m_component); // or whatever your member is
}
The question says that you don't want to use RTTI, but you fail to provide a reason. The common misundertandings are that RTTI is slow, if that is the case, consider profiling to see if that is your case. In most cases the slowness of dynamic_cast<> is not important, as dynamic_casts should happen rarely on your program. If dynamic_cast<> is a bottleneck, you should refactor so that you don't use it which would be the best solution.
A faster approach, (again, if you have a performance bottleneck here you should redesign, this will make it faster, but the design will still be broken) if you only want to allow to obtain the complete type of the object would be to use a combination of typeid to tests the type for equality and static_cast to perform the downcast:
template <typename T>
T* get() {
if (typeid(*m_component)==typeid(T))
return static_cast<T*>(m_component);
else
return 0;
}
Which is a poor man's version of dynamic_cast. It will be faster but it will only let you cast to the complete type (i.e. the actual type of the object pointed, not any of it's intermediate bases).
If you are willing to sacrifice all correctness (or there is no RTTI: i.e. no virtual functions) you can do the static_cast directly, but if the object is not of that type you will cause undefined behavior.

Is there anything inherently wrong with dynamic downcasting in C++?

I've heard it said several times that if you need to dynamically downcast then there may be something wrong with the design. I see it as a similar mechanism to COMs queryinterface, querying an object at run-time to see what interfaces it supports and then invoking the appropriate method(s) accordingly.
Is there anything wrong with this?
As with many other features of programming languages, there are appropriate uses (COM might be one such case), but in most cases it indicates that you have created a type hierarchy that is not rich enough for your needs (does not offer all the operations you need) or that you are forcing the inheritance relationship on types that are not really related (and thus have different sets of operations).
Note that this is also the case of the COM interface, where besides the basic publishing of what interfaces are supported, the objects share very little to nothing. But in that particular case, the binding of unrelated types in a hierarchy is a need of the particular interface defined in the system.
There's nothing inherently wrong with it, and sometimes it's appropriate, but it's often poor design to write code that makes decisions based on the dynamic type of an object. If you have something like this:
void foo(Base const *base) {
Derived1 const *derived1 = dynamic_cast<Derived1 const *>(base);
if (derived1) {
// Do stuff
}
Derived2 const *derived2 = dynamic_cast<Derived2 const *>(base);
if (derived2) {
// Do stuff
}
}
you'd probably be better off putting that functionality into the derived classes as a virtual function, and letting the language's built-in dynamic dispatch take care of figuring out which code to run. That way, if you add a Derived3 later, you don't have to find all the places in your code where you're checking for Derived or Derived2, and add a check for Derived3 as well. Just implement the virtual function in Derived3 and all the existing virtual function calls will work.