I have done a little research on dynamic_casting, and I read that it creates something called the RTTI,
which is loaded in RAM too at start-up. At some platforms this isn't supported too I think. So I was wondering if there was any good solution to avoid it.
Let's say I have Statement class
class Statement
{
std::list<Operand*> operands;
};
and a Operand is a class with more subclasses like, memory address, register, ect. ( For some wondering, I am trying to make an assembler.:P
I can't go downcasting with dynamic_cast, which is also bad if I could. But what if I added a enumeration to Operand, which defines it's Type, so I can downcast with static_cast by using it's type.
I could make it a const, and define it in the constructor of every subclass right?
I am looking forward to what you all think.
Christian
Making a type - is an option.
But consider making a generic interface for Operand. So your memory address, register, ect will inplement that interface and you will be able to treat them polymorphic.
In case you can't invent such interface - consider redesigning your classes because it looks like they don't need to have a common interface.
If you need code reuse - go with composition, not inheritance
If you decide you want to down cast, you may consider using an interface to get to the appropriate type. But, you could also list out the subclasses explicitly as well.
class Operand {
public:
enum Type { OT_Address, OT_Register, /*...*/ };
virtual Type type () const = 0;
virtual AddressOperand * isAddress () { return 0; }
virtual RegisterOperand * isRegister () { return 0; }
//...
};
Then, instead of a down cast, you would simply invoke the method associated with the type. The derived class would implement it:
class AddressOperand : public Operand {
public:
Operand::Type type () const { return Operand::OT_Address; }
AddressOperand * isAddress () { return this; }
//...
};
Related
I'm trying to create an overloaded function that will be called with the dynamic type of an object. I try to do this without interfering with the actual class structure underneath, as I don't have direct access (i.e. I cannot add virtual methods, etc.)
As a concrete example, let's think of an AST class structure that looks somewhat like this:
class ASTNode {}; // this one is fully abstract; i.e. there's a virtual void method() = 0;
class Assignment : ASTNode {};
class Expression : ASTNode {};
class StringExpr : Expression {};
class MathExpr : Expression {};
I want to write a function act that will take an instance of ASTNode as parameter and, depending on its actual dynamic type do something different.
The call will be something like this
std::shared_ptr<ASTNode> parsedAST = get_a_parsed_ASTNode(); // ... received from some parser or library
act(parsedAST);
Then, I want to act, depending on the dynamic type of the ASTNode.
void act(std::shared_ptr<MathExpr> expr)
{
// Do something with Math expressions, e.g. evaluate their value
};
void act(std::shared_ptr<StringExpr> expr)
{
// Do something with String expressions, e.g. write their value to the log
};
void act(std::shared_ptr<Expression> expr)
{
// do something with other types of expressions (e.g. Boolean expressions)
};
Currently though, I cannot call since they dynamic type will be maybe not the ``most concrete type''. Instead, I have to manually create a dispatcher manually as follows, but the method is a bit silly in my opinion, since it does literally nothing else but dispatch.
void act(std::shared_ptr<ASTNode> node_ptr)
{
if(std::shared_ptr<MathExpr> derived_ptr = std::dynamic_pointer_cast<MathExpr>(node_ptr))
{
act(derived_ptr);
}
else if(std::shared_ptr<StringExpr> derived_ptr = std::dynamic_pointer_cast<StringExpr>(node_ptr))
{
act(derived_ptr);
}
else if(std::shared_ptr<Expression> derived_ptr = std::dynamic_pointer_cast<Expression>(node_ptr))
{
// do something with generic expressions. Make sure that this is AFTER the more concrete if casts
}
else if( ... ) // more of this
{
}
// more else if
else
{
// default action or raise invalid argument exception or so...
}
};
This is especially annoying & error-prone since my class hierarchy has many (> 20) different concrete classes that can be instantiated. Also, I have various act-functions, and when I refactor things (e.g. add an act for an additional type), I have to make sure to pay attention to the correct order of if(dynamic_pointer_cast) within the dispatcher.
Also it's not that stable, since a change in the underlying class hierarchy will require me to change every dispatcher directly, rather than just the specific act functions.
Is there a better / smarter solution? Evidently I'd appreciate "native" solutions, but I'm willing to consider libraries too.
Never encountered such problem myself, but can think of the following solution.
Create you hierarchy that mimics original hierarchy, has virtual act, the base has base pointer, and each cast it to the corresponding derived pointer.
Now, to create the needed wrapper, you don't need properly ordered dynamic_cast, dispach on typeid string. So your dispatch is a map from string to wrapper factory.
Sure you need RTTI for typeid string, but you would need it for dynamic_cast as well.
I'm trying to write a lightweight library for parsing C source code.
Here's the way I've considered writing a declaration parser:
Decl CParser::ParseDecl(std::istream& in);
Or something like:
void CParser::Parse(std::istream& in);
// and
virtual void CParser::OnDecl(const Decl& decl);
Where Decl is a base class that may be inherited by either a TypedefDecl, FunctionDecl, or VariableDecl.
Is it okay that client code will have to cast into a derived class to get more information about the declaration? Or is there a better way to do this?
Edit:
The function itself isn't very well defined yet, it may actually be a callback, like CParser::OnDecl(const Decl& decl); which may be overloaded by a derived class like CFomatter: public CParser or something. That's not entirely part of the question.
I'm really just curious if it's okay that a client of the library will have to cast the Decl object. There's a lot of different declaration types in the C language (even more in C++) and it seems like writing a callback or a parser for each one of them would be just as bad as having to derive the base class.
First, of all you have to avoid slicing, for example by returning a a pointer.
Decl* CParser::ParseDecl(std::istream& in);
Then, generally speaking, forcing a client to cast a return value is a symptom of a bad design. What if he casts to the wrong type ? How shall he know to which type he has to cast ? If the user makes the wrong cast, it's undefined behaviour (and extremely nasty bugs).
CParser cp;
...
Decl* token = cp.ParseDecl(ifs);
FunctionDecl *ftoken;
VariableDecl *vtoken;
if (????) { // <============ how does your user know ?
ftoken = static_cast<FunctionDecl>(token);
//... do something with ftoken specific to function declarations
}
else if (????) {
vtoken = static_cast<VariableDecl>(token);
//... do something specific for variable declarations
}
To make the things more robust, you should at least make the type polymorphic, by having one or more virtual functions. Then your client can use the safer dynamic casting and make the right decision (which returns nullptr in case of wrong casting):
...
if (ftoken = dynamic_cast<FunctionDecl>(token)) { // If wrong type fotken will be set to nullptr and you go to the else part
//... do something with ftoken specific to function declarations
}
else if (vtoken = dynamic_cast<VariableDecl>(token)) { // attention: it's = and not ==
//... do something specific for variable declarations
}
This would be an acceptable design. But if you have polymorphic types, you could rethink your design by making use of this polymorphism, instead of forcing user to take care of casting. One possible way could for example be to define class specific functions as polymorphic ones:
class Decl {
public:
virtual void display_details() { cout << "No detail for this token"; }
...
};
class VariableDecl : public Decl {
...
display_details() { cout<<"This is variable "<<name; }
};
class FunctionDecl : public Decl {
...
display_details() { cout<<"This is function "<<name<<" with "<<nparam<< " parameters"; }
};
The user could then just refer to the specific building blocs, without worying to much about the real type of the object:
Decl* token = cp.ParseDecl(ifs);
token->display_details();
Another popular design for more complex situations is the visitor design pattern. This is for example used by boost::variant : it could be worth looking at their examples, event if you don't intend to use this library.
Lets say I have a class Handler with some subclasses like stringhandler, SomeTypeHandler, AnotherTypeHandler. The class Handler defines a method "handle" as a common interface for all the subclasses. The logic to "handle" is ofcourse completely different for the different handlers.
So what I need to do is pass a value of anything to the handle method. The specific classes can then cast the "anything" to the type they expect.
Basically what I need is something like the java class Object :D
The first thing I tried was a void*, but apparently you can not do B* someB = dynamic_cast<B*>(theVoidPointer), so no luck there.
My second idea was to use boost::any. however, the requirement to use boost::any is that the value must be copy cunstructable, which is not the case for my data.
Any ideas to get this to work?
Thanks
EDIT: Note that I know I could use a SomeData class with no members at all, and let my data be subclasses of that, but I am looking for a more generic approach which does not require me to make my own wrapper class.
Okay, here is a simple approach using boost::any to hold pointers to your datatypes. However, beware that boost::any adds some overhead code decreasing performance slightly (in most cases neglectible).. consider using boost::spirit::hold_any instead, or void* if you don't need type safety.
class Handler {
public:
void handle( boost::any value ) {
do_handle( value );
}
private:
virtual void do_handle( boost::any& value ) = 0;
};
template<class T>
class HandlerBase : public Handler {
private:
void do_handle( boost::any& value ) {
// here you should check if value holds type T*...
handle_type( *(boost::any_cast<T*>( value )) );
}
void handle_type( const T& value ) = 0;
};
class StringHandler : HandlerBase<std::string> {
private:
void handle_type( const std::string& value ) {
// do stuff
}
};
Now you can write lots of handler classes, deriving from HandlerBase, without assuming that the handled types have a common base class.
You can for example define a base class:
class BaseHandlerData {
...
};
Then derive your specific data classes, which are expected by your handlers:
class StringData: public BaseHandlerData {
...
};
class SomeData: public BaseHandlerData {
...
};
Then you should be able to pass a BaseHandlerData* argument to the handle method, and use something like:
void handle(BaseHandlerData *data) {
StringData* stringData = dynamic_cast<StringData*>(...);
// handle your string data here ...
}
to safely cast to your expected data type.
Gerald
Another alternative, getting more toward the C world, would be a union type (http://en.wikipedia.org/wiki/Union_(computer_science)#C.2FC.2B.2B). This would only allow you to pass the types you specifiy, not any type, but has the type of behavior you describe.
You need to have a base class called DataObject or something. All of your data types, (string, number, whatnot) are sub classes of DataObject. The you define Handle like this:
void Handle(DataObject *dataObject);
This is a much safer way to do what you want. To make it even better, the DataObject can even know what kind of data it contains. Then the handlers can check that they've been sent the right type of data.
You can do
B* someB = static_cast<B*>(theVoidPointer);
i have a class with the following structure:
class myClass
{
private:
int type;
classOne objectOne;
classTwo objectTwo;
public:
myClass(classOne object)
{
this->objectOne = object;
this->type = 0;
}
myClass(classTwo object)
{
this->objectTwo = object;
this->type = 1;
}
}
i now want a method returning an object of type classOne if type is 0 and of type classTwo if type is 1. I do not want two methods to achieve this. the classes have different structures.
Is this even possible? Any suggestions are appreciated :)
You can use Boost.Variant to do this. A variant can be constructed directly from any value convertible to one of its bounded types. Similarly, a variant can be assigned any value convertible to one of its bounded types. Heres how you could use it in your class:
class myClass
{
private:
boost::variant<classOne, classTwo> obj;
public:
myClass(classOne object) : obj(object)
{
}
myClass(classTwo object) : obj(object)
{
}
};
It also provides a very convenient boost::get to retrieve the value from the variant.
You can use that to supply code for each bounded type you have(ie classOne and classTwo). Here is an example:
if (classOne * x = boost::get<classOne>(&obj))
{
//Code for classOne
}
else if (classTwo * x = boost::get<classTwo>(&obj)
{
//Code for classTwo
}
However, such code is quite brittle, and without careful attention will likely lead to the introduction of subtle logical errors detectable only at runtime. Thus, real-world use of variant typically demands an access mechanism more robust than get. For this reason, variant supports compile-time checked visitation via apply_visitor. Visitation requires that the programmer explicitly handle (or ignore) each bounded type. Failure to do so results in a compile-time error.
Visitation of a variant requires a visitor object. Like this:
class object_visitor
: public boost::static_visitor<>
{
public:
void operator()(classOne & x) const
{
//Code for classOne
}
void operator()(classTwo & x) const
{
//Code for classTwo
}
};
With the implementation of the above visitor, we can then apply it to obj, as seen in the following:
boost::apply_visitor( object_visitor(), obj );
Unless the two types are related (in which case you can create a function that will return a pointer/reference to the common ancestor) you cannot do that directly in C++.
C++ is a statically typed language, meaning that the type of every expression must be known at compile time, but you are trying to define a function whose return type depends on runtime values.
Depending on the particular problem to solve, there might be different approaches that you could take, including using type erasure (return a boost::any, boost::variant or your own type-erasure).
ClassOne and ClassTwo need to have the same return type then either via inheritance or composition. i.e ClassOne and ClassTwo need to be subclasses of the same super class OR they need to impl the same interface.
I am not sure why you would not use templates for your case.
You can have something like below:
template <class ClassType>
class myClass
{
private:
int type;
ClassType object;
public:
myClass(ClassType object_in)
{
this->object = object_in;
/*
C++ doesn't support reflection so I don't think there
is a robust way of doing the following at runtime.
*/
type = /* Get Type at runtime */;
}
/*
Have another method which return object in a straigtforward way.
*/
};
However, then this become trivial. Any more insight into what your use case is, such that you have to know the type?
Update:
If the ClassType is going to be an Object, you can have a const static int TypeID member for the class, which is set at compile time. You can then use it determine the Type at runtime.
If they're completely different structures, with no common base then an alternative way you can return them from the same function is to use void*.
However that's bad form in C++, usually indicating a design failure - either use two different functions, or use a common base class.
It's apples and oranges. If you put an apple into an recipe that calls for an orange it won't be the same recipe anymore.
The use of type-id is a sign that you need virtual functions for myClass. Even if the other two classes are totally independent, the fact that they are returned by the same function could easily make them inherit a base class. And also you can just return a pair containing class1, class2 and one of them can be null.
The first problem is how you will determine the class of which type has been returned. I think it is possible to return a pointer to structure of this type
struct res {
myClass* c1;
ClassOne* c2;
} ;
The field of the not chosen class is NULL, the other points to the object.
The dynamic_cast operator is returning zero (0) when I apply to a pointer that points to an instance of a multiply inherited object. I don't understand why.
The hierarchy:
class Field_Interface
{
public:
virtual const std::string get_field_name(void) const = 0; // Just to make the class abstract.
};
class Record_ID_Interface
{
public:
virtual bool has_valid_id(void) const = 0;
};
class Record_ID_As_Field
: public Field_Interface,
public Record_ID_Interface
{
// This class behaves as a Field and a Record_ID.
// ...
}
// A demonstration function
void Print_Field_Name(const Field_Interface * p_field)
{
if (p_field)
{
cout << p_field->get_field_name() << endl;
}
return;
}
// A main function for demonstration
int main(void)
{
Record_ID_As_Field * p_record_id = 0;
p_record_id = new Record_ID_As_Field;
if (p_record_id)
{
// (1) This is the trouble line
Print_Field_Name(dynamic_cast<Field_Interface *>(p_record_id));
}
return 0;
}
I want to have the Record_ID_As_Field to be treated as a Field_Interface, but also fit in where Record_ID_Interface are required.
Why is dynamic_cast in (1) above returning 0, and how do I resolve this?
I am using Visual Studion 2008 on Windows XP.
Note: For simplicity, I am using fundamental pointers in this example. Actual code uses boost::shared_ptr.
Note: For simplicity, I am using fundamental pointers in this example. Actual code uses boost::shared_ptr.
And that's your problem right there: You cannot dynamic_cast a shared_ptr<A> to a shared_ptr<B> since those two types are not actually related to each other, even if A and B are.
Luckily in the specific case in your question the dynamic_cast shouldn't be necessary, since Record_ID_As_Field* should be implicitly convertible to a Field_Interface* (since the one is derived from the other). shared_ptr implements conversion operators that lift these implicit conversions to the respective shared_ptr objects, so shared_ptr<Record_ID_As_Field> should be implicitly convertible to shared_ptr<Field_Interface>.
If you leave out the dynamic_cast, it should work.
If you'd actually need to do a dynamic cast, you could use a special constructor provided by shared_ptr:
shared_ptr<Record_ID_As_Field> raf;
shared_ptr<Field_Interface> fi(raf, dynamic_cast<FieldInterface*>(raf.get());
(I'm not sure what would happen there if the dynamic_cast fails, so you should investigate what's the best way to handle that situation.)