The following syntax is from cocos2d
-(void) setLevelScene:(Class)klass
{
[[CCDirector sharedDirector] replaceScene: [CCTransitionFade transitionWithDuration:1 scene:[klass scene]]];
}
i want to change above cocos2d code to Cocos2dx, as i know there is no type such as Class in COCOS2DX.
How can i change the code particularly Class class type or any alternative type in cocos2dx?
Can you assist me to change the above code?
C++ doesn't have mechanism like isKindOf or class "that contain class name".
If you want to check that object is an instance of a class you can use dynamic cast.
dynamic_cast< Class* >(object) <- this line will return null if object isn't an instance of Class
Another way is to use virtual method like ClassName();
which you override in your every class and return a string with ClassName, for example:
std::string MainLayer::ClassName(){
return "MainLayer";
}
edit:
In your example I would write something like this
void setLevel(CCScene* scene){
CCDirector::sharedDirector->replaceScene(CCTransitionFade::create(1.0f, scene);
}
and call like that
setLevel(MainLayer::scene());
In this case you don't need any information about class in setLevel function. If you have many levels in your project good idea is use the Factory Method pattern.
void className:: setLevelScene(className* klass)
{
CCDirector::sharedDirector()->replaceScene(CCTransitionFade::create(1, klass));
}
Related
I'm learning C++ by programming a game. I'm using SDL to display my objects and a factory structure to keep it all organised.
I separated the first object (a car), the controls (keyboard) and the display (monitor).
In my main class I call the monitor class to display a window where I should draw the images. If a key is pressed, the car should react to that by redrawing the image.
The problem here is that I initialized the monitor in the main class and I can't access it in my car class..
I tried a variety of things, but nothing seems to do the trick.
So here is the main class
Game::Game(GuiFactory* factory) {
bool is_running = true;
Car* car = factory->createCar();
car->drawCar();
// create factory specific window
Monitor* monitor = factory->createMonitor();
// create factory specific keyboard
Keyboard* keyboard = factory->createKeyboard();
while (is_running) {
// keyboard input
string key_input = keyboard->getKeys();
if (key_input == "quit") {
is_running = false;
} else if (key_input != "") {
if(key_input == "right"){
car->turnRight(monitor);
}
}
}
}
I have a main car class and an SDLCar class, which inherits car.
class Car {
public:
Car();
virtual ~Car();
virtual void drawCar() = 0;
virtual void turnRight() = 0;
};
Here is where I'm confused:
class SDLCar : public Car {
public:
SDLCar();
virtual ~SDLCar();
void drawCar();
void turnRight(SDLMonitor& monitor);
// ^^^^^^^^^^^^^^^^^^^
};
Could someone please explain?
In your base class Car you have declared the method turnRight which takes no parameters.
In your derived class SDLCar you have declared a completely different method with the same name. The reason why it's a different method and not a function override is that its takes a parameter. It should be parameterless to override Car::turnRight.
And because it's not a function override, the rules of polymorphism don't apply. Thus you can't call SDLCar::turnRight(SDLMonitor&) from a Car pointer.
Right now is an excellent time to start using the override keyword. It prevents specifically these kind of programming errors. By marking a function with override:
void turnRight(SDLMonitor& monitor) override;
the compiler will automatically check that it actually overrides a function from the base class.
E.g. with the above declaration, the compiler would give you an error (or a warning at least). This would've helped you find your error right away and prevented more erroneous code such as car->turnRight(monitor).
So now that the error is found, you need to find a way to fix it. Either declare the base class turnRight to take a SDLMonitor& as well, or think of something else if that's not how it should behave.
IMO having to pass the game window to a method like turnRight seems weird. Why would turning a car need a window? I think turnRight should do just what it says on the tin: turn the car right. Nothing else.
I don't know why you're passing a window to the method but if it's for drawing, shouldn't the drawCar method handle that? I don't know your code, so I'll leave it up to you.
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.
Background:
In my game engine I have a generic 'script parser' which is used to create game entities by parsing a script file. So in code you would have something like MyEntity* entity = MyScriptParer::Parse("filename.scr");
Any class which is to be scriptable inherits from a generic base class. Internally in the game engine there are some specific classes that use this - particles, fonts etc and this all works nicely in the parser - see extract below
std::string line;
std::getline(ifs, line);
if (line == "[FONT]") {
CFont* f = new CFont();
f->readObject(ifs);
}
else if (line == "[PARTICLE]") {
CParticle* p = new CParticle();
p->readObject(ifs);
}
...
My problem comes with how to handle user defined classes i.e classes in the games that use the game engine. The base class has an abstract method readObject so anything which inherits must implement this method.
The issue is how would the parser know about the new class? E.g say I have a CVehicle class the parser would now need to know to recognise "[VEHICLE]" and also be able to create a new CVehicle
Is there any way to store a class type or something in an array/map so maybe I could have a function to register a list of class types with strings to provide a lookup for creating the new instances?
Bit of a long shot and may not be possible so if anyone has other suggestions on how to approach the parsing they will be welcomed
You can store a class type in an array/map via std::type_info
However, you cannot create a type from this, as it would require more RTTI than is available in C++. (like reflection in .NET).
However, you could store a function pointer to a class factory in such a map.
I.e.
typedef CBaseClass* (*pfnCreateClass)();
std::map<std::string, pfnCreateClass> mapCreate;
// Registering
// CMyCustomClass::GetClass() is a static method that creates a CMyCustomClass
mapCreate.insert(std::pair<std::string, pfnCreateClass>("[CUSTOM_CLASS]", CMyCustomClass::GetClass));
// Get class
std::map<std::string, pfnCreateClass>::const_iterator it = mapCreate.find(line);
if(mapCreate.end() != it)
{
CBaseClass *p = it->second();
p->readObject(ifs);
}
Just have the function to register a new type take in the name of the type and a function for creating the type.
Something like so:
void RegisterType( std::string name, std::function< BaseType() > createFunc );
When registering a new type you do it like so:
RegisterType( "Vehicle", [](){ return new CVehicle; } );
That way the parser can create all the derived types.
I'm writing an event-based messaging system to be used between the various singleton managers in my game project. Every manager type (InputManager, AudioManager, etc) is derived from a base Manager class and also inherits from an EventHandler class to facilitate message processing, as follows:
class Manager
{ ... }
class EventHandler
{ ...
virtual void onEvent(Event& e) =0;
...
}
class InputManager : public Manager, public EventHandler
{ ...
virtual void InputManager::onEvent(Event& e);
{ ... }
}
Elsewhere I have an EventManager that keeps track of all EventHandlers and is used for broadcasting events to multiple recievers.
class EventManager
{...
addHandlerToGroup(EventHandler& eh);
{ ... }
...
}
Naturally when I'm initializing all of my singleton Managers, I want to be adding them as they're created to the EventManager's list. My problem is that MVC++ complains at compile-time (and as I'm coding with squiggly lines) whenever I attempt to cast my Managers to EventHandlers. I thought it would work as follows:
int main()
{ ...
EventManager* eventM = new EventManager();
...
InputManager* inputM = new InputManager();
eventM->addHandlerToGroup(dynamic_cast<EventHandler>(inputM));
}
The compiler, however, informs me that "a cast to abstract class is not allowed." I was under the impression that you can...after all, polymorphism doesn't do you much good without passing objects back and forth with a bit of flexibility as to how close to the base class they are interpreted. My current workaround looks like this:
int main()
{ ...
EventManager* eventM = new EventManager();
EventHandler* temp;
...
InputManager* inputM = new InputManager();
temp = inputM;
eventM->addHandlerToGroup(*inputM);
}
Which, as far as I can tell, is the same conceptually for what I'm trying to accomplish, if a bit more verbose and less intuitive. Am I completely off as far as how typecasting with polymorphism works? Where am I going wrong?
in EventManager, declare the method addHandlerToGroup as
void addHandlerToGroup(EventHandler* handler);
then, just remove the cast. pass the pointer (in the example inputM) as it is to the addHandler method, and you should be fine :)
InputManager* inputM = new InputManager();
eventM->addHandlerToGroup(dynamic_cast<EventHandler>(inputM));
I think you just lost track of what you were doing. In this code, inputM is an InputManager* and you are trying to cast it to an EventHandler. That is, you are trying to cast a pointer to one class to an instance of another class. That, of course, makes no sense.
You can cast a pointer to an instance of a derived class to a pointer to an instance of one of its base classes. I think that's what you meant to do.
I have a C++ class 'Expression' with a method I'd like to use in my Objective-C class 'GraphVC'.
class Expression {
double evaluate(double);
}
And my Objective-C class:
#implementation GraphVC : UIViewController {
- (void)plot:(double(*)(double))f;
#end
I thought that it would be easiest to pass around function pointers that take a double and return a double, as opposed to C++ objects, but I haven't had much success using functional.h. What's the best way to use my C++ method from Objective-C?
EDIT: Thanks for your quick responses. Allow me to elaborate a bit... I have a backend written in C++ where I manipulate objects of type Expression. There's subclasses for rational, polynomial, monomial, etc. My initial idea was to use mem_fun from , but I wasn't able to get code compiling this way. I also had trouble using bind1st to bind the this pointer.
Writing an Objective-C wrapper is a possibility, but I'd rather use the already existing evaluate() function, and I don't want to break the clean separation between the backend and the iPhone GUI classes.
I can't have a global expression or use a static method (I need to plot arbitrary Expression instances.
I should have more explicitly stated that I need to pass a C++ member function (not a static function or existing C function) to an Objective-C object. Has anyone had luck using C++'s <functional> to turn member functions into pointers I can use in an Objective-C object, or should I use an Objective-C wrapper?
If you want to make a pointer to a method in C++, you need to include the class name, like this:
class Foo
{
public:
double bar(double d)
{
return d;
}
};
void call_using_obj_and_method(Foo *f, double (Foo::*m)(double d))
{
(f->*m)(3.0);
}
int main()
{
Foo f;
call_using_obj_and_method(&f, &Foo::bar);
return 0;
}
Note that you need an instance of the class as well. In my example this is another parameter, though you could let it be a global variable, or a singleton instance of class Foo.
Though, like jkp said, you can also solve the problem by making the method static or turning it into a regular function.
EDIT: I'm not sure if I understand your question correctly. I don't think you need to use functional. Here is how my example would look in Objective-C++:
#include <Cocoa/Cocoa.h>
class Foo
{
public:
double bar(double d)
{
return d;
}
};
typedef double (Foo::*fooMethodPtr)(double d);
#interface Baz : NSObject
{
}
- (void)callFooObj:(Foo *)f method:(fooMethodPtr)m;
#end
#implementation Baz
- (void)callFooObj:(Foo *)f method:(fooMethodPtr)m
{
(f->*m)(3.0);
}
#end
int main()
{
Foo f;
Baz *b = [[Baz alloc] init];
[b callFooObj:&f method:&Foo::bar];
return 0;
}
I would suggest wrapping the C++ class in an Objective-C class, and then also providing a
- (void) plotWithObject:(id)obj
{
double result = [obj evaluate: 1.5];
// ... etc ...
}
in addition to the plot: method.
I think the problem here is that you are trying to pass a member function of your Expression class to the Objective-C class. This will not work because it's expecting a this pointer as the first argument to that function (therefore the signature is not the same as the one expected by the plot: method.
If you make the C++ method a static, you can do this, but then you don't buy yourself a lot over using a standard C function.
IE, if the Expression class looked like this:
class Expression {
static double evaluate(double);
}
You should be able to call it like this:
[self plot:myExpression.evaluate(&Express::evalulate)];
As I say though, there isn't a huge amount of value in this because you may as well be using a standard C function (unless you can do something in the C++ class that is more useful to you).
I did once look at trying to bridge boost::bind() results with objective-c methods but didn't get very far. I'm sure if you dig deep enough in the C++ runtime you could do it though.
If your C++ member function returns a double, can't your code just look like this?
- (void)plot:(double)f;
...
[self plot:myExpression.evaluate(aDouble)];
Or something similar. I've not used much mixing of Obj-C and C++, but this is how I would approach it. You also might have to have a .mm extension on your Objective-C++ file if you're mixing them like that.
Why wouldn't you pass the instantiated c++ class around inside an NSValue and then call the c++ method directly?
- (NSValue*)getExpression
{
Expression* e = new Expression();
return [[NSValue alloc] initWithPointer:e];
}
- (void)callExpression(NSValue*)expression
{
Expression* e = [expression pointerValue];
e->evaluate();
}