C++ Inserting a class into a map container
Solution 1
First, don't store objects themselves in the map, store pointers to your objects.
Second, you need to give an instance of Scene_Branding to std::make_pair, not the class itself.
EDIT: Here's how you go about storing pointers:
string CurrentScene = "Scene_Branding";
map<string, Scene*> Scenes;
Scenes.insert(std::make_pair("Scene_Branding", new Scene_Branding()));
But, since you asked this type of question, i recommend you read a good c++ book for further grasping of concepts like pointers.
Solution 2
Try:
Scenes.insert(std::make_pair("Scene_Branding", Scene_Branding()));
Solution 3
I think you don't want to do that.
- there is no runtime type-mapping in C++, you store objects, not types.
- you cannot store polymorphic types in STL containers, use
boost::ptr_map
instead if it is your wish
So, the "new" code:
class Scene
{
public:
virtual ~Scene(); // Virtual Destructor, it's a base class
virtual Scene* clone() const = 0; // Polymorphic construction
private:
// whatever you wish
};
class Scene_Branding: public Scene
{
public:
virtual Scene_Branding* clone() const { return new Scene_Branding(); }
};
And the new way to store those:
const std::string SceneBrandingKey = "Scene_Branding";
typedef boost::ptr_map<std::string, Scene> scenes_type;
scenes_type Scenes;
Scenes.insert(SceneBrandingKey, new Scene_Branding());
And you can use it thusly:
Scenes["Scene_Branding"].process(); // Note: use '.' not '->'
The nice thing about Boost Pointer Container is that it's been meant for polymorphic types, with exception safety and all, and yet mimics the behavior / interface of the STL so that you are not lost :)
Solution 4
You need pointers in class when use generic map containers else, the result is possible a new object empty of your class... with pointers works!
std::map<std::string, Type*> map_;
Insert
map_["key"] = *Type;
NOTE: if -fpermisive flag to compiler is not set you need pass *Type not const when insert in the map_ container.
Best Regards,
Javier,
Related videos on Youtube
Fouf
Updated on June 14, 2020Comments
-
Fouf about 4 years
I have a map in C++ and I wish to input my class as the value, and a string as the key. When I try to, I get an error
'Scene_Branding' : illegal use of this type as an expression
I get an illegal use of this type as an expression, and I can't seem to find out why. Here is some code.string CurrentScene = "Scene_Branding"; map<string, Scene> Scenes; Scenes.insert(std::make_pair("Scene_Branding", Scene_Branding)); //<-- Illegal Error parameter 2
and here is Scene Branding header..
#ifndef Scene_Branding_H #define Scene_Branding_H #include "Scene.h" #include <iostream> #include <string> class Scene_Branding : Scene { public: Scene_Branding(); ~Scene_Branding(); void Draw(); }; #endif
and here is Scene header..
#ifndef Scene_H #define Scene_H #include <iostream> #include <string> class Scene { public: Scene(); ~Scene(); virtual void Draw(); }; #endif
and here is there cpp files.
Scene cpp.
#include "Scene.h" Scene::Scene() { } Scene::~Scene() { } void Scene::Draw(){ std::cout << "Hey"; }
Scene_Branding cpp
#include "Scene_Branding.h" Scene_Branding::Scene_Branding() { } Scene_Branding::~Scene_Branding() { } void Scene_Branding::Draw() { std::cout << "Drawing from Scene_branding"; }
-
codencandy over 14 yearsboth answers are correct in pointing out that you need an instance of Scene_Branding not just the type. one more hint make your base class destructor virtual
-
Admin over 14 yearsDo you really mean to use private inheritance?
-
-
kennytm over 14 yearsStoring objects is fine as long as the object's class is final.
-
Fouf over 14 yearsThis works, but the code is not as intended and cout is outputting Hey, and not Drawing from Scene_Branding.. hmm but thanks for the fix.
-
erelender over 14 yearsThis is because an instance of Scene is stored in the map, not an instance of Scene_Branding. This is called object slicing, briefly it causes you to lose information declared in Scene_Branding. Storing pointers will not cause this issue.
-
Fouf over 14 yearsHow would I go about handing it a pointer? I seem to just get errors such as error C2664: 'Scene::Scene(const Scene &)' : cannot convert parameter 1 from 'Scene_Branding (__cdecl *const )(void)' to 'const Scene &'
-
erelender over 14 yearsI think OP is a little newbie to be diving into boost yet.
-
Fouf over 14 yearsAha, I tried this, but I was mistakenly placing Scene_Branding .. anyway, thanks.
-
Dominic.wig over 14 yearsI'm not sure, but IMHO instead of virtual Scene_Branding* clone() const there should be virtual Scene* clone() const ;-)
-
Emile Cormier over 14 yearsIt's funny how everybody thinks C++ newbies need to learn to do things the error-prone manual way, before using libraries that make life easier.
-
Emile Cormier over 14 years+1 After the OP learns about the pitfalls of manual memory management, he/she will come to appreciate shared_ptr and ptr_container.
-
Emile Cormier over 14 years-1 because of slicing bug. I think you didn't see that the OP wants a container of polymorphic objects. :-)
-
erelender over 14 yearsOf course, things that make life easier are better but, in order to use high level stuff efficiently, one must understand low level stuff, don't you think? Don't give a lamborghini to a new driver.
-
Matthieu M. over 14 years@Dominic: no, it's correct because a
Scene_Branding*
is convertible to aScene*
(it's called covariant return). It means that by invoking thevirtual
method you get aScene*
but if you explicitly use theScene_Branding::clone
then you obtain aScene_Branding*
> if you have more type information, you get a more precise type in return :) -
Matthieu M. over 14 years@erelender: I only partially agree. I am not going to delve into template metaprogramming or preprocessor programming yet, it's too soon for the OP. On the other hand, why should I not show easy-to-use libraries ? I don't understand why people keep on teaching about
char*
manipulations in C++ becausestd::string
are more elaborate when you have strings in just about every other language... -
erelender over 14 years@Matthieu: I only partially agree also :). When you teach someone how to use std::string, he only learns how to use std::string. On the other hand teaching char* manupilations allows him to apply the concept of pointer manupilation to other types as well. I think learning a language should be about how stuff works under the hood, not how to use stuff. If one learns how stuff works, others will follow.
-
Ivan Talalaev over 5 years@kennytm could you clarify a little. What does it mean "as long as object's class is final? You mean final keyword? And why this final will do?
-
kennytm over 5 years@IvanTalalaev "final" means there are no subclasses to the
Scene
class. If there are subclasses then usingmap<string, Scene>
may cause object-slicing. A final class prevents this situation.