I have a token class that looks something like this:
class Token
{
public:
typedef enum { STRTOK, INTTOK } Type;
virtual bool IsA(Type) = 0;
}
class IntTok : public Token
{
int data;
public:
bool IsA(Type t) { return (t == INTTOK); }
int GetData() { return data; }
}
IntTok newToken;
if ( newToken.IsA(Token::INTTOK )
{
//blah blah
}
So essentially I have to have every subclass defined in the Token class; which doesn't turn out that bad because there are very few subclasses and I can't imagine them changing. But still, it's ugly, kludgy and less "correct" than identifying subclasses using a dynamic cast. However:
IntTok newToken;
IntTok* tmpTokenTest = dynamic_cast<IntTok*>(&newToken);
if ( tmpTokenTest != NULL )
{
//blah blah
}
Is also pretty kludgy. Particularly when I have to string them together in a large, nested if.
So which would you use? Is there another solution to this problem?
Note: I know that I'll have to cast them to get at their respective data anyways, but
I won't be casting them until right before I use their function, so it feels cleaner and
I test their type far more often then I use their data.
Note2: Not indicated in the code above is that these tokens are also a linked list. That makes templating difficult(a Token<int> may point to a Token<string>, etc). Which is why I need a Token class as a parent to begin with.
Just use virtual functions instead to do what you want. Instead of this:
if(newToken.IsA(Token::INTTOK))
{
// do stuff with ((IntTok*)&newToken)->GetData()
}
Do this:
class Token
{
public:
...
virtual void doTypeDependentStuff() {} // empty default implementation
}
class IntTok : public Token
{
public:
...
void doTypeDependent()
{
// do stuff with data
}
}
Visitor pattern, indeed.
class TokenVisitor {
public:
virtual ~TokenVisitor() { }
virtual void visit(IntTok&) = 0;
virtual void visit(StrTok&) = 0;
};
class Token {
public:
virtual void accept(TokenVisitor &v) = 0;
};
class IntTok : public Token {
int data;
public:
virtual void accept(TokenVisitor &v) {
v.visit(*this);
}
int GetData() { return data; }
};
Then just implement the visitor interface and call
token->accept(myVisitor);
Control will be given to the Visitor, which then can do the appropriate action(s). If you need to have the variable locally and of the right type - then however you will hardly get around down-casting it. But i think driving control to specific implementations using virtual functions often is a good way to solve it.
Might i suggest using Boost::Variant, which is basically the union of multiple types (an object of type variant can hold any object of type Ti ( 1 <= i <= n ) ).
Using this, you won't have to use inheritance.
See there for more information.
So essentially I have to have every subclass defined in the Token class
Can you explain why?
Is it really necessary to cast? Polymorphic functions can be put to use.
Or, maybe you can have a templated Token class (with default behavior for some) and specialize for the remaining.
That's a nasty one, though I would be more likely to go with the version of using RTTI.
Weren't new C++ compilers (I've last tried in VC 6.0 when it wasn't really supported) supposed the typeid operator so you wouldn't need a full dynamic cast?
Related
I am trying to implement a simple database interface than can handle different types, including custom classes. I wanted to pick inheritance or templates but it seems that I used both with no good results.
Header file
enum class RECORD_TYPE
{
TYPE_LONG = 11,
TYPE_STRING = 12
//other types
};
// the reason I created this class is to use it as function member parent
class RecordType
{
public:
RecordType(RECORD_TYPE record_type) : record_type_(record_type) {}
RECORD_TYPE get_record_type()
{
return record_type_;
}
protected:
RECORD_TYPE record_type_;
};
template<class T>
class RecordType_t : public RecordType
{
public:
RecordType_t(T value, RecordType type) : RecordType(type), value_(value) {}
const T &get_value() const { return value_; }
protected:
T value_;
};
class RecordType_long : public RecordType_t<long>
{
public:
RecordType_long(long value) : RecordType_t(value, RECORD_TYPE::TYPE_LONG) {};
};
class RecordType_string : public RecordType_t<std::string>
{
public:
RecordType_string(std::string value) : RecordType_t(value, RECORD_TYPE::TYPE_STRING) {};
};
Usage
void add_record(const RecordType &record)
{
//here I need to know the type(string/long/custom) because the types have to be stored different
switch (record.get_record_type())
{
case RECORD_TYPE::TYPE_LONG:
//long x = record.get_value();
case RECORD_TYPE::TYPE_STRING:
//string x = record.get_value();
//then do something with these values
};
};
Database db;
RecordType_string str("test");
db.add_record(str);
RecordType_long lng(200);
db.add_record(lng)
My main problem (apart from the fact that I am pretty sure it's bad design) is that in the function add() I don't have access to get_value() member function so I can get the values of each type. Because, of course, in the parent class, if I create the get_value(), I won't know what type to return.
Can you suggest how to implement better this thing?
Thank you
P.S. I could dynamically cast from RecordType into RecordType_long/RecordType_string/etc but I read here that this is really really bad design.:)
The problem is that templates provide a polymorphic behavior which is orthogonal to the one provided by inheritance.
The former provides parametric polimorphism while the latter provides subtyping.
These two different types of polymorphism doesn't mix together in C++. Each template specialization is a different type which is orthogonal to the others specialization of the same template, which means that there is no is-a relationship between such types as you have with inheritance.
So your choices really depend on the design you intend to use. To let each kind of field save itself on the database for example you would need to let each instance manage its own serialization without the need of knowing which is who, for example:
class SerializableRecord
{
public:
virtual void save(Database& db) const;
}
class RecordType_long : private RecordType_t<long>, public SerializableRecord
{
public:
void save(Database& db) const override {
long value = get_value();
/* save it on database somehow */
}
}
In this way you can use polymorphism and templates together but for two different purposes, without the need of knowing which specific kind of record you are going to save, of course this also implies that you need to work with pointers or object slicing occurs.
Another solution would be to make Database::save templated and specialize for various types:
class Database {
public:
template<typename T> void save(const T& record);
}
template<> void Database::save<RecordType_t<long>>(const RecordType_t<long>& record) {
long value = record.get_value();
// ...
}
Actually you have many options, it really depends what you need to achieve and the complexity of the structure itself.
I want a function return its real type, even it called in subclass. Here is the test code:
class Super
{
public:
Super(){};
virtual auto getSelf() -> decltype(*this)&
{
return *this;
}
void testSuper(){};
};
class Sub : public Super
{
public:
void testSub(){};
};
int main()
{
Sub().getSelf().testSuper();//OK
//Sub().getSelf().testSub();//Error
return 0;
}
In Objective-C, I can use instanttype to solve this.
But in C++, is it possible?
By the way, I do not want a template implementation, since it may increase the code size.
But in C++, is it possible?
Yes, and just like anything in C++, there is many ways to do it. But both ways require you to add something in the Sub class.
If you don't need virtual functions, then simply override (statically) that function:
struct Super {
auto getSelf() -> Super& {
return *this;
}
void testSuper(){};
};
struct Sub : Super {
auto getSelf() -> Sub& {
return *this;
}
void testSub(){};
};
int main() {
Sub().getSelf().testSuper(); //OK
Sub().getSelf().testSub(); //OK too!
return 0;
}
Of course, if you don't like copy pasting that code, you can always create a mixin class (a CRTP template):
template<typename Subclass>
struct AddGetSelf {
auto getSelf() -> Subclass& {
return static_cast<Subclass&>(*this);
}
};
You can the use that mixin in your classes like this:
struct Super : AddGetSelf<Super> {
using AddGetSelf<Super>::getSelf;
void testSuper(){};
};
struct Sub : Super, AddGetSelf<Sub> {
using AddGetSelf<Sub>::getSelf;
void testSub(){};
};
If you need virtual polymorphism, you can rely on covariant return types:
struct Super {
virtual auto getSelf() -> Super& {
return *this;
}
void testSuper(){};
};
struct Sub : Super {
auto getSelf() -> Sub& override {
return *this;
}
void testSub(){};
};
int main() {
Sub().getSelf().testSuper(); //OK
Sub().getSelf().testSub(); //OK too!
return 0;
}
Here's a live example at Coliru
If you are worried about binary size, consider static linking and link time optimisation.
I suggest you to try out both solutions and compare binary sizes, since template size increase can be cancelled out by compiler optimisation, and virtual polymorphism can prevent the compiler to do these optimisations.
I am going to go ahead with no. There is not convenient mechanisms in c++ to perform what you wish. (By convenient I mean avoiding any boilerplate, IMO options presented by Guillaume in his answer are certainly worth exploring.)
The code for different cases has to be duplicated. Types and objects cannot be created during run-time, like e.g. in C#. So you have to have code for each type.
You can do what you wish through static polymorphism, though those are templates. Maybe the compiler is smart enough to optimize each copy of getSelf, after all it's all returning the same pointer. But from the language point of view you have to provide a definition for each type.
There is run-time type information, but you would still need to if between the types effectively duplicating the code.
You might implement your example pure run-time using RTTI and dynamic cast, but it would be kinda ugly, as you would have to cast to reference manually... and dangerous.
E.g:
#include <iostream>
class Super
{
public:
Super(){};
virtual auto getSelf() -> decltype(*this)&
{
return *this;
}
void testSuper(){};
};
class Sub : public Super
{
public:
void testSub(){std::cout << "test\n"; };
};
int main()
{
Sub().getSelf().testSuper();//OK
dynamic_cast<Sub&>(Sub().getSelf()).testSub();//Danger
return 0;
}
But in C++, is it possible?
Short answer is - not directly as it happens in C#.
The type of this is the one of a pointer to the type of the subobject that offers the member function definition.
That is, Super * within getSelf definition in Super, Sub * within getSelf definition in Sub.
That said, note that the goal of double dispatching matches your requirements.
The drawback is that a call like Sub().getSelf().method(); is not possible anymore in this case.
It follows a minimal, working example:
struct Visitor;
struct Super
{
virtual void getSelf(Visitor &) = 0;
void testSuper(){}
};
struct Sub : Super
{
void getSelf(Visitor &) override;
void testSub(){}
};
struct Visitor
{
void accept(Sub &sub)
{
sub.testSuper();
sub.testSub();
}
};
void Sub::getSelf(Visitor &v)
{
v.accept(*this);
}
int main()
{
Visitor visitor;
Sub sub;
Super &super = sub;
super.getSelf(visitor);
}
What you want to be done as in Object-C is not possible in C++. They have different object calling models. See Object-C Messages. When you call object in C++ compiler must know everything about member function at compile time. In Object-C you don't call member function directly you send message to the object. So this is run-time binding.
I was just thinking about it and wondering if it's totally possible, just out of curiosity, as it would be very usefull I think. (but most of my ideas are crazy/insane anyway).
So here it goes:
Is it possible to create a class A, and class B, then add a member to class A by using class B?
Let's suppose we are making a game, or some program in which this would be usefull:
class Player
{
public:
float health;
};
Now, you think of a way to allow extensions by using include files or something:
#define INCLUDE_SPEEDO_METER
#ifdef INCLUDE_SPEEDO_METER
class PlayerSpeedo : public Player
{
public:
float absolute_speed;
//Do some Magic here & there
};
#endif
Now let's suppose we want to access the absolute speed of a player from the Player class like Player.absolute_speed.
Is this possible in any way?
No, that's not possible. You can't "inject" members into another class. Frankly, I can't see why you would ever want to. No one else than you would be aware of this "injected" member.
While you can't syntactically do what you are hoping to do, you can achieve something very close by storing a map in the base class.
class Player
{
public:
Player(float health = 0) { data["health"] = health; }
float health() const { return get("health"); }
float get(std::string const& field) const { return data[field]; }
protected:
std::map<std::string, float> data;
};
class PlayerSpeedo : public Player
{
public:
PlayerSpeedo(float absolute_speed) {data["absolute_speed" = absolute_speed; }
float absolute_speed() const { return get("absolute_speed"); }
};
What you're talking about is not possible in a statically typed language, but it would work in a dynamically typed language (like Python).
A way of achieving that in C++ would be to use a Map between string names of properties and some generic wrapper for property values.
Not quite what you're asking for, but would give you somewhat similar capabilities is the recent proposal for a future version of the C++ standard Call syntax: x.f(y) vs. f(x,y)
This would enable you to write a standalone function float absolute_speed(const Player& p) { return 0.0f; } that you could call via Player p; auto speed = p.absolute_speed() without changing the definition of Player. This is a similar idea to extension methods in C#.
Maybe you like the way which is often done to extend a base class by another class with a template like the following. There is no need for runtime polymorphism which is often a criteria for speed while optimizing can go down to the executed functions without stopping at the virtual functions.
As you can see from the example, it looks like injection of methods and attributes. C++11 offer it to use the constructor from the class which you use to extend the given class very simple. OK, this is a stupied example but maybe it give you an idea how the thing works.
#include <iostream>
class Empty
{
public:
void DoSomething() { std::cout << "Nothing" << std::endl;}
};
class Extender
{
private:
int x;
public:
Extender(int _x):x(_x) {}
void DoSomething() { std::cout << "Value " << x << std::endl; }
};
template <typename ExtendWith>
class User: public ExtendWith
{
public:
using ExtendWith::ExtendWith;
void DoIt() { ExtendWith::DoSomething(); }
};
int main()
{
User<Empty> userEmpty;
userEmpty.DoIt();
User<Extender> userExtended(100);
userExtended.DoIt();
}
I don't think the language could allow what you're trying to do without introducing inconsistencies.
I don't think you want to modify the actual type though, since what you describe is essentially converting a super-type instance into a sub-type instance. You could do this by adding a constructor to the sub-type...
class PlayerSpeedo : public Player {
public:
float absolute_speed;
explcit PlayerSpeedo(const Player& p, float absolute_speed=0, ...) : health(p.health) {
// copy Player values
}
Another option might be storing a reference to the original object, and decorating it. This doesn't alter the type though.
Hi i have a question regarding how to access parts of inherited code.
Say i have this WorldObject that is a base class for alot of other objects. Then i have a class Chest that inherit from WorldObject and also from the abstract class OpenAble, with some methods like open and unlock.
In my main i have a vector of WorldObjects that i iterate through with a for loop. Now to the question, how can i check if a worldobject is also of OpenAble and how can i access the methods in OpenAble.
class WorldObject
{
... //implementation
};
class OpenAble
{
public:
OpenAble(){}
virtual ~OpenAble(){}
virtual void Open() = 0;
virtual void Unlock(int k) = 0;
};
class Chest : public WorldObject, public OpenAble
{
... //implementation
};
main()
{
std::vector<WorldObject> objVector; //vector with several Worldobjects
for (int i =0; i < objVector.Size(); i++)
{
//check if a WorldObject is also of openable
//Do som actions like, open or unlock
//How?
}
};
You could do a dynamic_cast<OpenAble>. This will throw an error if it is the wrong type though which is relatively expensive given that it is quite likely that the object will be the wrong type.
try{
OpenAble& opener = dynamic_cast<OpenAble&>(worldObj);
} catch (std::bad_cast& ex){
//not openable
}
BTW: As pointed out in the comments below, if you use a pointer to the base class in your container instead of references, then you can (and should) use the pointer version of dynamic_cast which will return a null in the case that your object is not OpenAble. Checking that in your case would be a lot more efficient than throwing and catching exceptions.
I would recommend an entirely different approach though. Inject your base class with an "OpenPolicy".
E.g.
class CanOpenPolicy {
public:
boolean canOpen(){ return true; };
boolean canClose(){ return true; };
boolean isOpen(){ return openState; };
void open(){ openState = OPEN; };
void close(){ openState = CLOSED; };
}
class NoOpenPolicy {
public:
boolean canOpen(){ return false; };
boolean canClose(){ return false; };
boolean isOpen(){ return CLOSED; };
void open(){ throw IllegalWorldObjectAction("OpenPolicy disallows operation"); };
void close(){ throw IllegalWorldObjectAction("OpenPolicy disallows operation"); };
}
//injection via template (no need for base "OpenPolicy" class, maybe some
// obscure error codes at compile though)
// Implicit interface based on how you use the injected policy.
template<OpenPol>
class WorldObject {
private:
// CTOR part of the injected contract so you are not tied to knowing how to
// build the policy. This is a key benefit over interface based injection.
OpenPol openPol;
...
public:
...
void open(){
if(openPol.canOpen()){
openPol.open();
}
}
...
}
That's not tested or anything. Just to illustrate the idea. You can add multiple policies for different possible operations and the best thing is that you won't need a lot of hierarchies.
To use it just do something like this:
std::unique_ptr<WorldObject>( new Chest() );
std::unique_ptr<WorldObject>( new Banana() );
std::unique_ptr<WorldObject>( new Chair() );
where:
class Chest : public WorldObject<CanOpenPolicy> {
// Very little implementation in here.
// Most of it is handled in the base class and the injected policies :)
}
class Banana: public WorldObject<CanOpenPolicy> {
}
class Chair : public WorldObject<NoOpenPolicy> {
}
The most important thing, even though you may not like this, is to not throw away type information in the first place.
Collections of generic "object" is a Java'ism, it's not how to do things in C++.
That said, provided the statically known class is polymorphic (has at least one virtual member function), you can use dynamic_cast or typeid. This functionality is known as RTTI, short for Run Time Type Information. With some compilers you have to use special options to enable RTTI.
Idiomatic use of dynamic_cast:
WorldObject* p = ...;
if( auto p_openable = dynamic_cast<OpenAble*>( p ) )
{
// use p_openable
}
Note that dynamic_cast to pointer signals failure by returning a nullpointer, while dynamic_cast to reference signals failure by throwing an exception, since there are no nullreferences.
The simple (obvious) solution is to use dynamic_cast and cast your objects to OpenAble.
The problem with "the simple (obvious) solution" is that usually, use of dynamic_cast shows a lack of flexibility in your class hierarchy and is a symptom of a design problem.
I would offer the OpenAble interface as a set of behavior exposed through a handle:
class OpenAble { /* ... */ };
class WorldObject
{
//implementation
virtual OpenAble* GetOpener() { return nullptr; }
};
class Chest: public WorldObject {
struct ChestOpener: public OpenAble {
Chest *c;
virtual void Open() {
// do stuff with c
}
};
std::unique_ptr<OpenAble> chest_opener;
public:
virtual OpenAble* GetOpener() {
if(!chest_opener) {
chest_opener = new ChestOpener{ this };
}
return chest_opener.get();
}
};
Client code:
std::vector<WorldObject> objVector; //vector with several Worldobjects
for(auto &obj: objVector)
{
if(auto openerHandle = obj.GetOpener())
openerHandle->Open();
}
I'm writing a piece of generic software that will be loaded on to many different variants of the same basic hardware. They all have the same processor, but with different peripherals and their own functions that need to be carried out. The software will know which variant it should run by reading a hardware switch value.
Here's my current implementation in a nutshell:
class MyBase
{
public:
MyBase() { }
virtual run() = 0;
}
class VariantA : public MyBase
{
public:
VariantA () { }
virtual run()
{
// Run code specific to hardware Variant-A
}
}
class VariantB : public MyBase
{
public:
VariantB () { }
virtual run()
{
// Run code specific to hardware Variant-B
}
}
void main()
{
MyBase* variant;
uint_8 switchValue = readSwitchValue();
switch(switchValue)
{
case 0:
variant = new VariantA();
break;
case 1:
variant = new VariantB();
break;
}
variant->run();
}
Now this works just fine. I read the hardware value and use a switch statement to create the new corresponding class.
The problem is that there are a lot of variants I have to deal with. Currently about 15, with the potential to add another 20-30 in the near future. I have really come to despise switch statements that run for hundreds of lines, so I'm really looking for a better way to do this, probably through templates.
I want to be able to use my hardware value to look up a type and use that type to create my new object. Ideally when I add a new variant, I create the new class, add that class type to my lookup table with it's matching hardware value, and it's good to go.
Is this possible at all? What's a good solution here?
As stated, you make a factory, but not necessarily with naive switch statements. What you can do is make a template class to create the relevant object and dynamically add these to your factory.
class VariantinatorBase {
public:
VariantinatorBase() {}
virtual ~VariantinatorBase() {}
virtual std::unique_ptr<Variant> Create() = 0;
};
template< class T >
class Variantinator : public VariantinatorBase {
public:
Variantinator() {}
virtual ~Variantinator() {}
virtual std::unique_ptr<Variant> Create() { return std::make_unique<T>(); }
};
Now you have a class factory that allows you to register these.
class VariantFactory
{
public:
VariantFactory()
{
// If you want, you can do all your Register() calls in here, and even
// make the Register() function private.
}
template< uint8_t type, typename T >
void Register()
{
Register( type, std::make_unique<Variantinator<T>>() );
}
std::unique_ptr<Variant> Create( uint8_t type )
{
TSwitchToVariant::iterator it = m_switchToVariant.find( type );
if( it == m_switchToVariant.end() ) return nullptr;
return it->second->Create();
}
private:
void Register( uint8_t type, std::unique_ptr<VariantinatorBase>&& creator )
{
m_switchToVariant[type] = std::move(creator);
}
typedef std::map<uint8_t, std::unique_ptr<VariantinatorBase> > TSwitchToVariant;
TSwitchToVariant m_switchToVariant;
};
At the beginning of your program, create the factory and register your types:
VariantFactory factory;
factory.Register<0, VariantA>();
factory.Register<1, VariantB>();
factory.Register<2, VariantC>();
Then later, you want to call on it:
std::unique_ptr<Variant> thing = factory.Create( switchValue );
You are looking for a factory
http://www.oodesign.com/factory-pattern.html
A factory is a software module (a method, a class) whose sole purpose is to create the right object for the job. An example using a factory class:
class VariantFactory
{
MyBase* CreateObject(uint_8 value);
}
And the CreateObject method can be filled out to give you the type of object that you need.
In the case of a very small selection of objects with simple construction, a simple switch statement might suffice. As soon as you get a lot of objects or ones that require more detailed construction, a factory is quite useful.
I made this a comment; let's turn it into an answer:
Personally, I think a "switch/case" block to create the appropriate class is probably an optimal solution. Just put your case statement in a static "factory" method that returns a reference to the specific class. IMHO...
Here's a good example: factory method design pattern
Class Book : public Product
{
};
class Computer : public Product
{
};
class ProductFactory
{
public:
virtual Product* Make(int type)
{
switch (type)
{
case 0:
return new Book();
case 1:
return new Computer();
[...]
}
}
}
Call it like this:
ProductFactory factory = ....;
Product* p1 = factory.Make(0); // p1 is a Book*
Product* p2 = factory.Make(1); // p2 is a Computer*
// remember to delete p1 and p2
Note that in his most excellent response, smink also suggests some other design alternatives, too.
BOTTOM LINE: There's nothing inherently "wrong" with a switch/case block. Even for a switch with many case options.
IMHO...
PS:
This really isn't creating a "dynamic type". Rather, it's "creating a static type dynamically". That would be equally true if you used a template or an enum solution as well. But again - I vastly prefer the "switch/case".
Update: I am leaving my original solution here for posterity, but consider the solution provided by paddy to be superior and less error prone. With only a couple of slight improvements I think it's actually about as good as you can possibly get.
Consider this design:
class VariantA : public MyBase
{
static MyBase *CreateMachineInstance() { return new VariantA; }
};
class VariantB : public MyBase
{
static MyBase *CreateMachineInstance() { return new VariantB; }
};
Now, all you need is an std::map that uses a uint_8 as the key and maps it to a function pointer (returning MyBase). Insert the identifiers in the map (pointing each to the appropriate machine creation function) and then read the code and just use the map to find what machine you're using.
This is loosely based on a concept/pattern called a "factory" but may break slightly if your machine constructors require different arguments or you need to perform additional per-machine initialization/operations - and from what you mention it sounds like you might.
If that's the case, you can still use this pattern but you will have to make some tweaks and rearchitect things a bit but you will end up with something much cleaner and easier to augment and maintain.
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
template<class T,class T1>
class HeroHonda
{
private:
T millage;
T1 *options;
public:
HeroHonda() {
puts("constructed");
options=new T1[20];
strcpy(options,"Good millage,Powerstart");
millage=110;
}
virtual T features() {
cout<<options<<"millage is"<<millage<<endl;
return 1;
}
// virtual T Extrafeatures() = 0;
~HeroHonda() {
cout<<"destructor"<<endl;
delete [] options;
}
};
int main()
{
HeroHonda <int,char> *Ptr=new HeroHonda <int,char>;
Ptr->features();
delete Ptr;
}