Creating an object based on a string parsed in

Suppose I have a class Image. At some point in the parsing, the "Image" is read at the appropriate time, that is, I want to create a class object Image.

What I am considering is matching these lines with calling the constructor in the appropriate class, but I'm not sure how to do this.

those.

container.push_back( some_map[stringParsedIn] ); // basic idea
+3
source share
4 answers

, Factory (, Image ). , , , if/else. ( , ):

typedef Image* create_image_function();

template <class T>
Image* create_image(SomeType arg)
{
    return new T(arg);
}

...
map<string, create_image_function*> creators;
creators["Foo"] = &create_image<Foo>;
creators["Bar"] = &create_image<Bar>;
creators["Baz"] = &create_image<Baz>;

shared_ptr<Image> ImageFactory::make_image(const string& str)
{
    // checking to see if str exists as a key 
    // would be nice
    return shared_ptr<Image>(creators[str](arg));
}
+2

factory. , if/else.

Image "". , .

:

class Media {
 public:
  virtual Save() = 0;
};

class Image : public Media {
 public:
   Image() { }
   virtual Save() { ... }
};

class Sound : public Media {
 public:
   Sound() { }
   virtual Save() { ... }
};

- factory:

Media *CreateMedia(const string &type) {
  if (type == "Image") {
    return new Image;
  } else if (type == "Sound") {
    return new Sound;
  } else {
    // handle invalid type error
  }
}

, CreateMedia , factory/registry :

// This is some mechanism to create types of Media.
template <typename T>
struct CreatorFunction {
  Media *operator() {
    return new T;
  }
};

// This is the factory that the types will register with.
class Factory {
 public:
  // singleton access function.
  static Factory* Get() {
    static Factory* f = new Factory; 
    return f;
  }

  // Creates Media of the given type.
  Media* Create(const string& name) { return registry_[name](); }

  // Records 'name' with the creator function 'func'.
  void Add(const string& name, const CreatorFunction &func) {
    registry_.insert(name, func);
  }
 private:
  Factory() { } // users can't create factories, they can only use singleton.
  hash_map<string, CreatorFunction> registry_;
};

#define REGISTER_MEDIA(type) Factory::Get()->Add(#type, CreatorFunction<type>);

REGISTER_MEDIA(Image);  // usually goes with the Image class.
REGISTER_MEDIA(Sound);  // usually goes with the Sound class.

int main(int argc, char** argv) {
  string parsedIn = "Image";
  Factory::Get()->Create(parsedIn);
}

, , , . , if/then, - . , , .

0

, , , ..

Image *createImage() {
    return new Image();
}

.

std::map<std::string, Image *(*)()> constructorMap;
constructorMap.insert(std::pair<std::string, Image *(*)()>("Image", createImage));

Image *myImage = constructorMap["Image"]();
0

100%, , .

:

Image* makeImage(ArgType arg) { return new Image(arg); }

And then you can store pointers on your map!

map["Image"] = makeImage;

Call them later!

SuperclassOfImage soup = map["Image"](arg);

Of course, the limitation is that function type signatures must accept the same type argument and must return the same type (an instance of a class that is either an image or an image parent).

0
source

Source: https://habr.com/ru/post/1751494/


All Articles