0

I want to create an object of a class with name of a string already known by me i.e dynamically.

Suppose i have a class A and a string str="ab" so I should create an object A ab; but I can't specify "ab" as it should be like A str,as str may vary dynamically.

Benjamin Bannier
  • 55,163
  • 11
  • 60
  • 80
  • 2
    Not possible in C++ - there is no reflection unlike in java – Constantin Dec 04 '13 at 09:41
  • 2
    What would a use case of that be? – Benjamin Bannier Dec 04 '13 at 09:42
  • You could be trying to serialize an object to string. – Extrakun Dec 04 '13 at 09:43
  • 3
    What would be the point - how would you refer to such an object elsewhere in the code? – Kerrek SB Dec 04 '13 at 09:44
  • Oh wait. I think I read the question wrong. Now I don't know what you want anymore. _Sigh._ – sbi Dec 04 '13 at 09:55
  • Let me clear my point again,suppose I have a class Test and i have to create an object of this class,From my code dynamically i got to know that name of the class should be temp_1 as it has already been defined and initialized some values so noe I want to have an object of class Test as temp_1 but i cant give this name directly i have this name stored in a string,with the help of this string i want to name the object of the class – user3065186 Dec 04 '13 at 10:25
  • @user3065186: Read the comments written to you. They are asking _why_ you think you want to do that, and are trying to encourage you to realise that you may have jumped to a proposed [impossible] solution before telling us about the problem. – Lightness Races in Orbit Dec 04 '13 at 11:00

4 Answers4

4

You could use a map data structure, with the key being name of the class, and the value being a factory class for creating the object, or a pointer to a function which when run, will return the object. However, you may need to cast the constructed object to your desired type.

Example (apologies for my rusty C++ code):

First, we have an interface for a factory class

class IObjectFactory 
{
     public:
    virtual ~IObjectFactory() {}
    virtual void* Create() = 0;

};

Then, a concrete implementation. I'll just do inline.

class ConcreteObjectFactory : public IObjectFactory
{
    public:
    void* Create() { return new ConcreteObject(); }
};

Now for the map.

using namespace std;
map<string, shared_ptr<IObjectFactory> > classMap;

// register the type
classMap["concreteObject"].reset( new ConcreteObjectFactory() );

// using it, albeit you take all kinds of risks if the string is not found
// or points to the wrong type.

ConcreteObject* o = 
    static_cast<ConcreteObject *>( classMap["concreteObject"]->Create() );

There are many ways to improve this answer. For those interested, I'll suggest checking out the chapter on RTTI in "C++ for Games Programmers"

Extrakun
  • 19,057
  • 21
  • 82
  • 129
  • 1
    I think she wants to use a runtime variable as an identifier. – Benjamin Bannier Dec 04 '13 at 09:43
  • @BenjaminBannier: I think that's what he *thinks* he wants. But in my experience, just about every single time someone thinks they want something like this, what they really want is a map, they just don't know how to ask for it properly (if they did, they would probably already know about maps, and wouldn't need to ask the question). -- With that said, what I really think the OP is looking for is simply `map`. – Benjamin Lindley Dec 04 '13 at 09:56
  • @BenjaminLindley: Yes, that makes sense. Maybe Extrakun can add an example to his answer to make it clearer how this is a solution. – Benjamin Bannier Dec 04 '13 at 09:59
  • 1
    I fixed your code to the extent of making it C++. Better is to use boost::any – CashCow Dec 04 '13 at 15:46
  • @CashCow: Thanks, been out of touch with C++ for a long time. – Extrakun Dec 04 '13 at 16:23
  • Use of void* is particularly poor here. Your alternative option is some base class from which any class registered this way must derive. Then you can use that base class followed by a safe "dynamic_cast". You would also, of course, check that the entry exists within the map.; – CashCow Dec 05 '13 at 10:20
1

The name of a variable is not part of the program, or more precisely, the name doesn't exists within memory. It is just a "handle" or a "sign" to let the programmers easily access the variable, ie. find where the content of the variable resides in memory.

In other words, after a piece of code has been compiled to object file, the names doesn't exists any more.

In your case, "ab" is actually the content in memory, when "ab" emerges in memory, your program already runs at run-time, at that time there is no variable names at all.

Daniel King
  • 407
  • 4
  • 11
  • Thanks for your ans but in my case I have used ab object and initialized it and I have so many objects of class A like ab which are already defined and initialize but I want them to access again according to some user choice that's why I want the name of the object to be given dynamically,is there any way to do that ? – user3065186 Dec 04 '13 at 10:43
  • Do you mean that you have already instantiated bunch of objects, but you want to use one of them dynamically by providing a name tag to specify which exact object you really want? If so, you can build a map(for example, std::map objs; ), the keys for the map can be names such as "ab", and then you can get a specific object by objs["ab"]. – Daniel King Dec 04 '13 at 11:27
0

I do not think it is possible .. if anyone gives you an answer, you can work around the problem in this way:

class A {
public:
  A(const std::string& name) : name_(name) {}
  inline std::string name() { return name_; } 
private:
  std::string name_;
}

in this way you have an implicit conversion from string to A, so:

std::string className = "myName";
std::cout << (A)className->name(); /* print "myName" */

Otherwise you could use a map data structure as suggest Extrakun.

Luca Davanzo
  • 21,000
  • 15
  • 120
  • 146
0

It is possible in some circumstances to go from a name to a variable of that name that already exists (i.e. not create it now). That works with dlsym on UNIX or GetProcAddress on Windows. The symbol must be visible, thus a global and in Windows explicitly exported from the library. Beware of name "mangling" issues.

It is not possible to create one that way, other than, of course, the workaround of code-generation then, assuming a compiler is present, building that into a library.

In your case you probably want to use a map from a string to variables, and if you want the same map to be able to store different value types, you can use boost::any as the value type of your map.

CashCow
  • 30,981
  • 5
  • 61
  • 92