如何从具有不同构造函数的超类访问子类的成员?

Eri*_*ans 0 c++ inheritance constructor subclass superclass

我有以下类和typedef:

class Object

{
protected:
    long int id;
public:
    Object(void);
    ~Object(void) {};
    long int get_id(void);
};

typedef map<string, Object> obj_map;
Run Code Online (Sandbox Code Playgroud)

然后我有了它的孩子:

class Image: public Object

{
private:
    path full_path;
    int x;
    int y;
    img image;
public:
    Image(path p, int x_pos = 0, int y_pos = 0);
    ~Image(void) {};

    void draw(int flags = 0);
    void move_north(float velocity);
    void move_south(float velocity);
    void move_west(float velocity);
    void move_east(float velocity);

    path get_path(void);
    img get_image(void);
    int get_x(void);
    int get_y(void);
    void set_path(path p);
    void set_image(img _image);
    void set_x(int value);
    void set_y(int value);
};
Run Code Online (Sandbox Code Playgroud)

每个对象都存储在名为App的类中的静态映射obj_map中.所以让我们假设我们在关键foo下有一个对象.我们可以这样打印它的id:

cout << App::objects.find("foo")->second.get_id() << endl;
Run Code Online (Sandbox Code Playgroud)

现在,让我们假设我已将Image对象作为值传递给此映射.当我尝试访问它时,我可以正常访问id.但是,当我尝试访问Image方法时:

cout << App::objects.find("foo")->second.get_x() << endl;
Run Code Online (Sandbox Code Playgroud)

我得到一个:

error: 'class Object' has no member named 'get_x'
Run Code Online (Sandbox Code Playgroud)

那是因为类Object实际上没有它.所以,我尝试施展它:

cout << static_cast<Image>(App::objects.find("foo")->second).get_x() << endl;
Run Code Online (Sandbox Code Playgroud)

我明白了:

error: no matching function for call to 'Image::Image(Object&)'
Run Code Online (Sandbox Code Playgroud)

如果我尝试使用dynamic_cast,我会得到一些可怕的东西......

error: cannot dynamic_cast 'App::objects.std::map<_Key, _Tp, _Compare, _Alloc>::find<std::basic_string<char>, Object, std::less<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, Object> > >((* & std::basic_string<char>(((const char*)"foo"), (*(const std::allocator<char>*)(& std::allocator<char>()))))).std::_Rb_tree_iterator<_Tp>::operator-><std::pair<const std::basic_string<char>, Object> >()->std::pair<const std::basic_string<char>, Object>::second' (of type 'class Object'
Run Code Online (Sandbox Code Playgroud)

我不明白.构造函数不是继承的.构造函数与它无关.Image对象有一个完全不同的构造函数,但它是一个Object.重点是:我无法创建图像映射,因为最终我的引擎中会有很多对象,我希望能够从超类中访问它们.

M.M*_*M.M 5

这张地图:

typedef map<string, Object> obj_map;
Run Code Online (Sandbox Code Playgroud)

只存储Object对象.当你试图放入Image时,它会被切掉,你会丢失图像中实际上不属于它的所有内容Object.

您似乎正在寻找的行为称为多态.要激活它,您必须做两件事:

  • 使Object多态
  • 存储指向地图中对象的指针

第一部分是简单的:添加virtual之前~Object(void).

对于第二部分,有三种开箱即用的方法:

map<string, Object *>              // 1
map<string, unique_ptr<Object>>    // 2
map<string, shared_ptr<Object>>    // 3
Run Code Online (Sandbox Code Playgroud)

这些选项之间的区别在于您希望如何管理这些对象的生命周期.

如果地图应该拥有对象使用(2)或(3).如果单个对象可能出现在地图中的多个位置,或者您希望能够复制地图,或者地图外部可能存在引用相同对象的引用,请使用(3); 否则使用(2).

如果你使用(1)你必须要小心的对象是否正确deleteð 后,他们在地图上最后一次使用.

您可能需要#include <memory>使用智能指针类.

插入对象看起来分别如下:

map["foo"] = new Image(....);
map["foo"] = make_unique<Image>(....);
map["foo"] = make_shared<Image>(....);
Run Code Online (Sandbox Code Playgroud)

您实际上可以使用from new或者.reset()最后两个,但make_函数是首选样式.