繁体   English   中英

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

[英]How can I access the members of a subclass from a superclass with a different constructor?

我有以下类和typedef:

class Object

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

typedef map<string, Object> obj_map;

然后我有了它的孩子:

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);
};

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

cout << App::objects.find("foo")->second.get_id() << endl;

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

cout << App::objects.find("foo")->second.get_x() << endl;

我得到:

error: 'class Object' has no member named 'get_x'

那是因为Object类实际上没有它。 因此,我尝试将其转换为:

cout << static_cast<Image>(App::objects.find("foo")->second).get_x() << endl;

我明白了:

error: no matching function for call to 'Image::Image(Object&)'

如果我尝试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'

我不明白 构造函数未继承。 构造函数与此无关。 Image对象具有完全不同的构造函数,但它是一个对象。 关键是:我无法创建图像映射,因为最终引擎中将有许多对象,并且我希望能够从超类访问它们。

这张地图:

typedef map<string, Object> obj_map;

仅存储Object对象。 当您尝试放入Image时,会将其切成薄片,并且丢失Image中实际上不是Object一部分的所有内容。

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

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

第一部分很简单:在~Object(void)之前添加virtual

对于第二部分,有三种现成的方法可以做到这一点:

map<string, Object *>              // 1
map<string, unique_ptr<Object>>    // 2
map<string, shared_ptr<Object>>    // 3

这些选项之间的区别在于您如何管理这些对象的生存期。

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

如果使用(1),则必须注意对象上一次使用正确delete d。

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

插入对象分别如下所示:

map["foo"] = new Image(....);
map["foo"] = make_unique<Image>(....);
map["foo"] = make_shared<Image>(....);

实际上,您可以对后两个使用new.reset()赋值,但是make_函数是首选样式。

您应该在地图中存储指向对象的指针 ,而不是对象(最好是shared_ptr ):

typedef map<string, shared_ptr<Object>> obj_map;
obj_map my_map;
path some_path; // I have no idea what 'path' is and how to use it or even create it
my_map.insert(make_pair("image1",make_shared<Image>(some_path, 0,0)));
my_map.insert(make_pair("image2",make_shared<Image>(some_path, 5,5)));
my_map.insert(make_pair("image3",make_shared<Image>(some_path, 10,10)));
auto iter = my_map.find("image3");
auto pImg = dynamic_pointer_cast<Image>(iter->second);
cout << pImg->get_x() << endl; //this should display '10'

Image放入定义为map<string, Object> obj_map您正在 Image对象截断Object (基类)。 换句话说,您的地图将始终存储并且仅存储Object元素(不存储Image )。 如果存储指针,则存储实际类的对象(只需将它们存储为指向基类的指针)。 因为没有任何内容被截断-您始终可以将指针强制转换为派生类并访问其方法。

希望对您有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM