I have a base class named shapes with derived class of a 3D shape, i.e. Ball or Tetraeder.
My program should read the type of the shape and it's parameters from a text file and write the volume and area to an output text.
#include <fstream>
#include <string>
#include <sstream>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include "Shape.h"
#include "Ball.h"
#include <vector>
using namespace std;
int
main( int argc, char** argv )
{
string input = string(argv[1]);
string output = string(argv[2]);
ifstream file(input);
string line;
string shapename;
int nx = atoi(argv[3]);
int ny = atoi(argv[4]);
int nz = atoi(argv[5]);
while (std::getline(file, line))
{
std::stringstream lineStream(line);
lineStream >> shapename;
int value;
std::vector<int> lineData;
while (lineStream >> value)
{
lineData.push_back(value);
}
Shape * objShape = new shapename(lineData);
objShape -> calc_volume;
objShape -> calc_projection(nx,ny,nz);
std::ofstream f(output);
f << objShape -> get_volume() << " " << objShape -> get_projection << endl;
}
}
My Question is now how can i create an object from a string in a textfile, especially without knowing all derived classes.
It should be possible to add more shapes to the program without changing the code, only by adding new files.
The question is:
My Question is now how can i create an object from a string in a
textfile, especially without knowing all derived classes.
The answer is: you have to know all the derived classes.
C++ does not have reflection. As such all class names are bound at compile time, and this kind of a factory has no choice but to do some variation of:
if (name == "box")
return new Box();
else if (name == "circle")
return new Circle();
// ... etc ... etc ...
There are various different approaches and design patterns that make it possible to automate some of this drudge work, and make this flexible enough to avoid having to explicitly maintain a hardcoded list of all subclasses.
I'll just outline a brief, very brief approach. A very simple one that I've used before, and achieves, pretty much, the same result: a factory that can instantiate a given subclass by name, in a manner where you don't have to manually edit the factory, and add a few more lines of code. The entire process of creating a factory for a new subclass can be neatly wrapped into the process of creating a new subclass, making this a fairly bulletproof, compartmentalized solution.
Consider a simple mechanism for registering a factory for these subclasses:
typedef Shape (*shape_factory_t)();
Shape is your superclass of shapes.
The factory would work something like this:
std::map<std::string, shape_factory_t> all_factories;
void register_factory(const std::string &name, shape_factory_t factory)
{
all_factories[name]=factory;
}
So now you have a map of all your factories. Instead of an endless if statement you have a single map, which you can look up by class name, and call the appropriate factory, something like:
auto iter=all_factories.find(name);
if (iter == all_factories.end())
throw; // Some exception, unknown subclass
return (*iter->second)();
All right, that part's taken care of. The issue now becomes: how to register a factory for each subclass.
Let's say you have an implementation of Circle:
class Circle : public Shape {
class initializer;
// ... other things that make up the Circle
};
Then, in circle.cpp, which implements this subclass:
static Shape *create_circle()
{
return new Circle(); // Add constructor parameters, as appropriate
}
class Circle::initializer {
public:
initializer() {
register_factory("circle", create_circle);
}
};
static initializer initialize_me;
In this manner, the Circle class registers itself with the factory that creates an instance of a given Shape, by class name. You can proceed and implement all other subclasses, individually, without touching the main factory code. You can declare your Box subclass in the same manner, and have it register itself with the factory, which will then automatically know to create a Box class (presumably by invoking the create_box() function), given the name "box".
There is one other detail that needs to be taken care of: initialization order. As you know, the relative initialization order of globally-scoped objects in different translation units is implementation defined, and is otherwise unspecified by C++.
The global std::map of all factory functions must be constructed before all the subclasses try to register themselves, and put themselves into the map, when the application starts.
This is a fairly typical static initialization order fiasco question, for which there are several known solutions. The one explained in this answer should work fine, here.
C++ isn't so flexible. Adding new shapes would mean adding new classes (since you have already made a Shapes, a Ball and a Tetraeder class, I'm assuming you want to make more classes). And if you add new classes, you'll have to change the code, which means you have to recompile.
You have to know what the derived classes are. You're the one who codes them, so you might as well also have a list of them. The best thing you can do about your program being flexible is using header files, which you already seem to be doing anyway.
As for creating an object from a string in a text file (while you know what the 3D object classes are), you can parse the string, read what kind of a shape it wants to make and then do something fairly simple such as this:
//shapeType - a string containing the type of the 3D object
Shape *newShape;
switch(shapeType) {
case "ball":
newShape = new Ball(...); // ... - parameters for the ball dimensions
break;
case "tetraeder":
newShape = new Tetraeder(...); // ... - parameters again
break;
default:
return -1;
}
//and now you can use newShape as you wish
Related
I have a school project in which there is a world simulation. Teacher wants me to do save/load system and I've encountered a problem. My data is saved in a format name x y so saving works fine.
Problem starts when I want to load data. This is my solution:
switch(name) {
case "Human":
new Human(x,y);
break;
case "Dog":
new Dog(x,y);
break;
}
Is there a way to generalize this? Saved name is always exactly the same as constructor name, so I would just like to do something like:
string name = "Human"
new <name>(x,y) <-> new Human(x,y);
My solution works just fine but following the rules of OOP, the world shouldn't know what kind of organisms live on it.
No, currently there isn't. C++ doesn't have reflection and introspection which is required for something like this to work. (There is active work being done in this direction, but don't expect it to come into standard very soon).
There are serialization libraries which will hide the equivalent of your intended switch and provide a simpler, safer API and they are the preferred way to do this in production, but for your assignment you should do it manually.
By the way, your code is syntactically incorrect, it shouldn't compile, but I guess I get what you meant.
You can simplify the process of string comparison using macros. But you still have to provide a list of classes that need to be searched.
#define CHECK_RETURN(name, className) if (name == #className) return new className();
std::string name = "Dog";
CHECK_RETURN(name, Human);
CHECK_RETURN(name, Dog);
CHECK_RETURN(name, Banana);
No. Not in C++. To do that you would need reflection, and that is not a thing C or C++ can do.
What is done in some cases is to write an Interface Definition Language, aka IDL, and from that generate code that implements the interface. These interfaces often include the ability to serialize and deserialize objects in order to send them across the network, but it works for files as well.
That's probably more than you want to get into.
What you want for a simple C++ project is to implement a Factory. I assume all these things are Organisms so you want an OrganismFactory like:
class OrganismFactory {
public:
static std::unique_ptr<Organism> Create(const std::string& line);
};
And then it reads the contents of a line and produces an Organism. Probably using something like your case statements. Or you can create a std::map or std::unordered_map of the class name and a function pointer to the rest of the line. Then there's no if or case for each object type, just a map lookup and an indirect function call. You still have to write the code to fill in the map though, and write each function.
And yes by OOP rules you need to create interfaces/virtual methods in the Organism base class for everything that Organisms do in the world.
You can create your own lookup table of creator functions to handle this, for example:
class Organism
{
public:
virtual ~Organism() {}
};
class Human : public Organism
{
...
};
class Dog : public Organism
{
...
};
...
using OrganismPtr = std::unique_ptr<Organism>;
using CreateFunc = OrganismPtr(*)(int, int);
std::map<std::string, CreateFunc> mymap;
mymap["Human"] = [](int x, int y) -> OrganismPtr { return new Human(x, y); }
mymap["Dog"] = [](int x, int y) -> OrganismPtr { return new Dog(x, y); }
...
string name = "Human";
OrganismPtr o = mymap[name](x, y);
// use o as needed...
I am trying to write my code without using global variable as most people told me it was a bad habit, so I am changing how my program works.
I am having problem with passing multiple instance of a class to another class. I need to be able to modify the multiple instance of a class in the other class.
Here is what I am trying to do but failing miserably at it :
int main() {
Players *player[6];
//preparing 6 instances of Players() so I can loop through them in another class
for (int i = 0;i<6;i++){
player[i] = new Players();
}
player[0]->name = "fluffy";
Players.h
#ifndef PLAYERS_H_
#define PLAYERS_H_
#include <string>
#include <vector>
class Players {
public:
Players();
virtual ~Players();
std::string name;
bool hand;
int cif;
int id;
std::vector<int> autho;
std::vector<int> collec;
std::vector < std::vector <int> > puppet;
};
#endif /* PLAYERS_H_ */
Players.cpp
#include "Players.h"
Players::Players() {
// TODO Auto-generated constructor stub
name = "";
hand = false;
cif = -1;
id = -1;
}
Players::~Players() {
// TODO Auto-generated destructor stub
}
Now I want to call another class (doesn't matter which) and I want to pass the multi instanced class Players to it so it can read and do modification to the data within these instanced classes.
For example a class with a function that could read player[0]->name and modify it to "sandpaper"
How would you approach this without getting errors from the compiler?
I am open to suggestion for a completely different way to approach this ( I have tried to use struct variables and pass it but I got other problems as well)
thank you,
Kaven
First of all, I'd approach this by using std::vector<Players> (not pointers!). Secondly, I'd just pass this vector by reference to other functions.
I suggest to approach like this:
int main()
{
unique_ptr<vector<Player>> playersVector (new vector<Player>);
for (int i = 0;i<6;i++)
{
playersVector->push_back(Players());
}
playersVector->at(0).name = "fluffy";
}
And then if you want to pass that vector with ownership to some method or class use:
move(playersVector)
If you want have ownership in main class pass by normal pointer:
playersVector.get()
I also suggest using Get/Set methods instead of accessing class fields directly
I was recently in a job interview and my interviewer gave me a modeling question that involved serialization of different shapes into a file.
The task was to implements shapes like circle or rectangles by first defining an abstract class named Shape and then implements the various shapes (circle, rectangle..) by inheriting from the base class (Shape).
The two abstract methods for each shape were: read_to_file (which was supposed to read the shape from a file) and write_to_file which supposed to write the shape into a file.
All was done by the implementation of that virtual function in the inherited shape (Example: For Circle I was writing the radius, for square I saved the side of the square....).
class Shape {
public:
string Shape_type;
virtual void write_into_file()=0;
virtual void read_into_files()=0;
Shape() {
}
virtual ~Shape() {
}};
class Square: public Shape {
public:
int size;
Square(int size) {
this->size = size;
}
void write_into_file() {
//write this Square into a file
}
void read_into_files() {
//read this Square into a file
}
};
That was done in order to see if I know polymorphism.
But, then I was asked to implement two functions that take a vector of *shape and write/read it into a file.
The writing part was easy and goes something like that:
for (Shape sh : Shapes) {
s.write_into_file();
}
as for the reading part I thought about reading the first word in the text (I implemented the serializable file like a text file that have this line: Shape_type: Circle, Radius: 12; Shape_type:Square...., so the first words said the shape type). and saving it to a string such as:
string shape_type;
shape_type="Circle";
Then I needed to create a new instance of that specific shape and I thought about something like a big switch
<pre><code>
switch(shape_type):
{
case Circle: return new circle;
case Square: return new square
......
}
</pre></code>
And then, the interviewer told me that there is a problem with this implementation
which I thought was the fact that every new shape the we will add in the future we should also update int that big swicht. he try to direct me into a design pattern, I told him that maybe the factory design pattern will help but I couldn't find a way to get rid of that switch. even if I will move the switch from the function into a FactoryClass I will still have to use the switch in order to check the type of the shape (according to the string content i got from the text file).
I had a string that I read from the file, that say the current type of the shape. I wanted to do something like:
string shape_type;
shape_type="Circle";
Shape s = new shape_type; //which will be like: Shape s = new Circle
But I can't do it in c++.
Any idea on what I should have done?
In you factory you could map a std::string to a function<Shape*()>. At startup you register factory methods will the factory:
shapeFactory.add("circle", []{new Circle;});
shapeFactory.add("square", []{new Square;});
shapeFactory.add("triangle", []{new Triangle;});
In your deserialization code you read the name of the type and get its factory method from the factory:
std::string className = // read string from serialization stream
auto factory = shapeFactory.get(className);
Shape *shape = factory();
You've now got a pointer to the concrete shape instance which can be used to deserialize the object.
EDIT: Added more code as requested:
class ShapeFactory
{
private:
std::map<std::string, std::function<Shape*()> > m_Functions;
public:
void add(const std::string &name, std::function<Share*()> creator)
{
m_Functions.insert(name, creator)
}
std::function<Shape*()> get(const std::string &name) const
{
return m_Functions.at(name);
}
};
NOTE: I've left out error checking.
In C++, with
for (Shape sh : Shapes) {
s.write_into_file();
}
you have object slicing. The object sh is a Shape and nothing else, it looses all inheritance information.
You either need to store references (not possible to store in a standard collection) or pointers, and use that when looping.
In C++ you would to read and write some kind of type tag into the file to remember the concrete type.
A virtual method like ShapeType get_type_tag() would do it, where the return type is an enumeration corresponding to one of the concrete classes.
Thinking about it, though, the question was probably just getting at wanting you to add read and write functions to the interface.
You could create a dictionary of factory functions keyed by a shape name or shape id (shape_type).
// prefer std::shared_ptr or std::unique_ptr of course
std::map<std::string, std::function<Shape *()>> Shape_Factory_Map;
// some kind of type registration is now needed
// to build the map of functions
RegisterShape(std::string, std::function<Shape *()>);
// or some kind of
BuildShapeFactoryMap();
// then instead of your switch you would simply
//call the appropriate function in the map
Shape * myShape = Shape_Factory_Map[shape_type]();
In this case though you still have to update the creation of the map with any new shapes you come up with later, so I can't say for sure that it buys you all that much.
All the answers so far still appear to have to use a switch or map somewhere to know which class to use to create the different types of shapes. If you need to add another type, you would have to modify the code and recompile.
Perhaps using the Chain of Responsibility Pattern is a better approach. This way you can dynamically add new creation techniques or add them at compile time without modifying any already existing code:
Your chain will keep a linked list of all the creation types and will traverse the list until it finds the instance that can make the specified type.
class Creator{
Creator*next; // 1. "next" pointer in the base class
public:
Creator()
{
next = 0;
}
void setNext(Creator*n)
{
next = n;
}
void add(Creator*n)
{
if (next)
next->add(n);
else
next = n;
}
// 2. The "chain" method in the Creator class always delegates to the next obj
virtual Shape handle(string type)
{
next->handle(i);
}
);
Each subclass of Creator will check if it can make the type and return it if it can, or delegate to the next in the chain.
I did create a Factory in C++ some time ago in which a class automatically registers itself at compile time when it extends a given template.
Available here: https://gist.github.com/sacko87/3359911.
I am not too sure how people react to links outside of SO but it is a couple of files worth. However once the work is done, using the example within that link, all that you need to do to have a new object included into the factory would be to extend the BaseImpl class and have a static string "Name" field (see main.cpp). The template then registers the string and type into the map automatically. Allowing you to call:
Base *base = BaseFactory::Create("Circle");
You can of course replace Base for Shape.
I need to make, for my college homework, an interpreter in C++ for a language based on functions (or commands). The interpreter has got to read an input file, extract the words (strings), generate the commands and execute them. All commands are classes which inherit from a common super-class (Command, for example), which's got a virtual method called execute. For each word read from the input file, a command is created and stored in a vector<Command>.
So, I'm thinking of using a hashtable, whose keys are the names of the commands (strings) and whose values are some kind of objects which allow me to create an specific class (or give me access to the constructor of an specific class), to easily create the classes for each word instead of using a chain of if-else-if's.
By now, I'm planning to create a CommandGenerator class with a virtual method called generate which returns a new Command object. The values of my commands hash table will be objects of theCommandGenerator class. So I derive from it many other subclasses for all commands, which return specific new objects derived from Command.
But, does anything like that already exist? Or is there any more elegant way to do that? Is there any kind of object that can be extracted from a class to represent it?
If each command is a subclass of Command, why don't you use a std::vector<Command*> and push pointers to instances of each subclass? Then you can iterate over the vector and call your virtual execute function.
The closest thing you can get about placing classes in a vector is boost::fusion::vector. But can't be filled at runtime, no use on your specific case.
Assuming you can use C++11. If you can define commands as just a execute function, you can do something like:
map<string, function<void()>> cmds = {
make_pair("print1", [](){
cout << "1" << end;
}),
make_pair("print2", [](){
cout << "2" << end;
}),
make_pair("print3", [](){
cout << "3" << end;
})
};
And then put the command on a vector with:
vector<function<void()>> list;
list.push_back(cmds["print1"]);
list.push_back(cmds["print1"]);
list.push_back(cmds["print2"]);
Then just execute with a loop:
for (function<void()>& cmd : list)
cmd();
This should print 112 to screen. But if you care a lot with speed, do a lot of ifs instead.
The basic problem you have is: You have the name of the class as a string and want to create a class with that name. This translation you have to do somehow manually, like you mentioned. This has been discussed here several times, like in Instantiating classes by name with factory pattern or in Looking for a better C++ class factory. The only addition I would make here: use good old macros, because they have a stringize-operator. E.g.:
#include <stdio.h>
#define CREATEOBJ(clss,command) if (strcmp (#clss, command)==0) return new clss;
class Base {
public:
virtual const char *name()=0;
};
class A : public Base {
public:
const char *name() {return "I am an A";}
};
class B : public Base {
public:
const char *name() {return "I am an B";}
};
Base *makeInstance (const char *nm) {
CREATEOBJ(A,nm);
CREATEOBJ(B,nm);
}
int main () {
printf ("%s\n", makeInstance ("A")->name());
printf ("%s\n", makeInstance ("B")->name());
}
of course you can make it nicer by using a hash-table containing the strings and some function-pointer or generator-class pointer, but the idea remains the same: to add a new class, just add one more CREATEOBJ-thingy.
In Java, you can have a List of Objects. You can add objects of multiple types, then retrieve them, check their type, and perform the appropriate action for that type.
For example: (apologies if the code isn't exactly correct, I'm going from memory)
List<Object> list = new LinkedList<Object>();
list.add("Hello World!");
list.add(7);
list.add(true);
for (object o : list)
{
if (o instanceof int)
; // Do stuff if it's an int
else if (o instanceof String)
; // Do stuff if it's a string
else if (o instanceof boolean)
; // Do stuff if it's a boolean
}
What's the best way to replicate this behavior in C++?
boost::variant is similar to dirkgently's suggestion of boost::any, but supports the Visitor pattern, meaning it's easier to add type-specific code later. Also, it allocates values on the stack rather than using dynamic allocation, leading to slightly more efficient code.
EDIT: As litb points out in the comments, using variant instead of any means you can only hold values from one of a prespecified list of types. This is often a strength, though it might be a weakness in the asker's case.
Here is an example (not using the Visitor pattern though):
#include <vector>
#include <string>
#include <boost/variant.hpp>
using namespace std;
using namespace boost;
...
vector<variant<int, string, bool> > v;
for (int i = 0; i < v.size(); ++i) {
if (int* pi = get<int>(v[i])) {
// Do stuff with *pi
} else if (string* si = get<string>(v[i])) {
// Do stuff with *si
} else if (bool* bi = get<bool>(v[i])) {
// Do stuff with *bi
}
}
(And yes, you should technically use vector<T>::size_type instead of int for i's type, and you should technically use vector<T>::iterator instead anyway, but I'm trying to keep it simple.)
Your example using Boost.Variant and a visitor:
#include <string>
#include <list>
#include <boost/variant.hpp>
#include <boost/foreach.hpp>
using namespace std;
using namespace boost;
typedef variant<string, int, bool> object;
struct vis : public static_visitor<>
{
void operator() (string s) const { /* do string stuff */ }
void operator() (int i) const { /* do int stuff */ }
void operator() (bool b) const { /* do bool stuff */ }
};
int main()
{
list<object> List;
List.push_back("Hello World!");
List.push_back(7);
List.push_back(true);
BOOST_FOREACH (object& o, List) {
apply_visitor(vis(), o);
}
return 0;
}
One good thing about using this technique is that if, later on, you add another type to the variant and you forget to modify a visitor to include that type, it will not compile. You have to support every possible case. Whereas, if you use a switch or cascading if statements, it's easy to forget to make the change everywhere and introduce a bug.
C++ does not support heterogenous containers.
If you are not going to use boost the hack is to create a dummy class and have all the different classes derive from this dummy class. Create a container of your choice to hold dummy class objects and you are ready to go.
class Dummy {
virtual void whoami() = 0;
};
class Lizard : public Dummy {
virtual void whoami() { std::cout << "I'm a lizard!\n"; }
};
class Transporter : public Dummy {
virtual void whoami() { std::cout << "I'm Jason Statham!\n"; }
};
int main() {
std::list<Dummy*> hateList;
hateList.insert(new Transporter());
hateList.insert(new Lizard());
std::for_each(hateList.begin(), hateList.end(),
std::mem_fun(&Dummy::whoami));
// yes, I'm leaking memory, but that's besides the point
}
If you are going to use boost you can try boost::any. Here is an example of using boost::any.
You may find this excellent article by two leading C++ experts of interest.
Now, boost::variant is another thing to look out for as j_random_hacker mentioned. So, here's a comparison to get a fair idea of what to use.
With a boost::variant the code above would look something like this:
class Lizard {
void whoami() { std::cout << "I'm a lizard!\n"; }
};
class Transporter {
void whoami() { std::cout << "I'm Jason Statham!\n"; }
};
int main() {
std::vector< boost::variant<Lizard, Transporter> > hateList;
hateList.push_back(Lizard());
hateList.push_back(Transporter());
std::for_each(hateList.begin(), hateList.end(), std::mem_fun(&Dummy::whoami));
}
How often is that sort of thing actually useful? I've been programming in C++ for quite a few years, on different projects, and have never actually wanted a heterogenous container. It may be common in Java for some reason (I have much less Java experience), but for any given use of it in a Java project there might be a way to do something different that will work better in C++.
C++ has a heavier emphasis on type safety than Java, and this is very type-unsafe.
That said, if the objects have nothing in common, why are you storing them together?
If they do have things in common, you can make a class for them to inherit from; alternately, use boost::any. If they inherit, have virtual functions to call, or use dynamic_cast<> if you really have to.
I'd just like to point out that using dynamic type casting in order to branch based on type often hints at flaws in the architecture. Most times you can achieve the same effect using virtual functions:
class MyData
{
public:
// base classes of polymorphic types should have a virtual destructor
virtual ~MyData() {}
// hand off to protected implementation in derived classes
void DoSomething() { this->OnDoSomething(); }
protected:
// abstract, force implementation in derived classes
virtual void OnDoSomething() = 0;
};
class MyIntData : public MyData
{
protected:
// do something to int data
virtual void OnDoSomething() { ... }
private:
int data;
};
class MyComplexData : public MyData
{
protected:
// do something to Complex data
virtual void OnDoSomething() { ... }
private:
Complex data;
};
void main()
{
// alloc data objects
MyData* myData[ 2 ] =
{
new MyIntData()
, new MyComplexData()
};
// process data objects
for ( int i = 0; i < 2; ++i ) // for each data object
{
myData[ i ]->DoSomething(); // no type cast needed
}
// delete data objects
delete myData[0];
delete myData[1];
};
Sadly there is no easy way of doing this in C++. You have to create a base class yourself and derive all other classes from this class. Create a vector of base class pointers and then use dynamic_cast (which comes with its own runtime overhead) to find the actual type.
Just for completeness of this topic I want to mention that you can actually do this with pure C by using void* and then casting it into whatever it has to be (ok, my example isn't pure C since it uses vectors but that saves me some code). This will work if you know what type your objects are, or if you store a field somewhere which remembers that. You most certainly DON'T want to do this but here is an example to show that it's possible:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int a = 4;
string str = "hello";
vector<void*> list;
list.push_back( (void*) &a );
list.push_back( (void*) &str );
cout << * (int*) list[0] << "\t" << * (string*) list[1] << endl;
return 0;
}
While you cannot store primitive types in containers, you can create primitive type wrapper classes which will be similar to Java's autoboxed primitive types (in your example the primitive typed literals are actually being autoboxed); instances of which appear in C++ code (and can (almost) be used) just like primitive variables/data members.
See Object Wrappers for the Built-In Types from Data Structures and Algorithms with Object-Oriented Design Patterns in C++.
With the wrapped object you can use the c++ typeid() operator to compare the type.
I am pretty sure the following comparison will work:
if (typeid(o) == typeid(Int)) [where Int would be the wrapped class for the int primitive type, etc...]
(otherwise simply add a function to your primitive wrappers that returns a typeid and thus:
if (o.get_typeid() == typeid(Int)) ...
That being said, with respect to your example, this has code smell to me.
Unless this is the only place where you are checking the type of the object,
I would be inclined to use polymorphism (especially if you have other methods/functions specific with respect to type). In this case I would use the primitive wrappers adding an interfaced class declaring the deferred method (for doing 'do stuff') that would be implemented by each of your wrapped primitive classes. With this you would be able to use your container iterator and eliminate your if statement (again, if you only have this one comparison of type, setting up the deferred method using polymorphism just for this would be overkill).
I am a fairly inexperienced, but here's what I'd go with-
Create a base class for all classes you need to manipulate.
Write container class/ reuse container class.
(Revised after seeing other answers -My previous point was too cryptic.)
Write similar code.
I am sure a much better solution is possible. I am also sure a better explanation is possible. I've learnt that I have some bad C++ programming habits, so I've tried to convey my idea without getting into code.
I hope this helps.
Beside the fact, as most have pointed out, you can't do that, or more importantly, more than likely, you really don't want to.
Let's dismiss your example, and consider something closer to a real-life example. Specifically, some code I saw in a real open-source project. It attempted to emulate a cpu in a character array. Hence it would put into the array a one byte "op code", followed by 0, 1 or 2 bytes which could be a character, an integer, or a pointer to a string, based on the op code. To handle that, it involved a lot of bit-fiddling.
My simple solution: 4 separate stacks<>s: One for the "opcode" enum and one each for chars, ints and string. Take the next off the opcode stack, and the would take you which of the other three to get the operand.
There's a very good chance your actual problem can be handled in a similar way.
Well, you could create a base class and then create classes which inherit from it. Then, store them in a std::vector.
The short answer is... you can't.
The long answer is... you'd have to define your own new heirarchy of objects that all inherit from a base object. In Java all objects ultimately descend from "Object", which is what allows you to do this.
RTTI (Run time type info) in C++ has always been tough, especially cross-compiler.
You're best option is to use STL and define an interface in order to determine the object type:
public class IThing
{
virtual bool isA(const char* typeName);
}
void myFunc()
{
std::vector<IThing> things;
// ...
things.add(new FrogThing());
things.add(new LizardThing());
// ...
for (int i = 0; i < things.length(); i++)
{
IThing* pThing = things[i];
if (pThing->isA("lizard"))
{
// do this
}
// etc
}
}
Mike