如何从具有不同构造函数的超类访问子类的成员?
How can I access the members of a subclass from a superclass with a different constructor?
我有以下 class 和 typedef:
class Object
{
protected:
long int id;
public:
Object(void);
~Object(void) {};
long int get_id(void);
};
typedef map<string, Object> obj_map;
然后我有它的 child:
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);
};
每个 object 都存储在这个静态映射 obj_map 中,在一个名为 App 的 class 中。所以让我们假设我们在键 foo 下有一个 object。我们可以这样打印它的id:
cout << App::objects.find("foo")->second.get_id() << endl;
现在,假设我已将图像 object 作为值传递给此地图。当我尝试访问它时,我可以正常访问id。但是,当我尝试访问 Image 方法时:
cout << App::objects.find("foo")->second.get_x() << endl;
我得到一个:
error: 'class Object' has no member named 'get_x'
那是因为 class 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'
我不明白。构造函数不被继承。构造函数与它无关。图像 object 具有完全不同的构造函数,但 它是 一个 Object。重点是:我无法创建图像映射,因为最终我的引擎中会有很多 Object,我希望能够从 superclass 访问它们。
这张地图:
typedef map<string, Object> obj_map;
仅存储 Object
个对象。当您尝试将 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
(基础class)。换句话说,您的地图将始终仅存储 且仅存储 Object
元素(而不是 Image
)。如果你存储指针 - 你存储实际 class 的对象(你只是将它们存储为指向基 class 的指针)。因为没有任何内容被截断 - 您始终可以将指针转换为派生的 class 并访问其方法。
希望对您有所帮助。
我有以下 class 和 typedef:
class Object
{
protected:
long int id;
public:
Object(void);
~Object(void) {};
long int get_id(void);
};
typedef map<string, Object> obj_map;
然后我有它的 child:
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);
};
每个 object 都存储在这个静态映射 obj_map 中,在一个名为 App 的 class 中。所以让我们假设我们在键 foo 下有一个 object。我们可以这样打印它的id:
cout << App::objects.find("foo")->second.get_id() << endl;
现在,假设我已将图像 object 作为值传递给此地图。当我尝试访问它时,我可以正常访问id。但是,当我尝试访问 Image 方法时:
cout << App::objects.find("foo")->second.get_x() << endl;
我得到一个:
error: 'class Object' has no member named 'get_x'
那是因为 class 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'
我不明白。构造函数不被继承。构造函数与它无关。图像 object 具有完全不同的构造函数,但 它是 一个 Object。重点是:我无法创建图像映射,因为最终我的引擎中会有很多 Object,我希望能够从 superclass 访问它们。
这张地图:
typedef map<string, Object> obj_map;
仅存储 Object
个对象。当您尝试将 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
(基础class)。换句话说,您的地图将始终仅存储 且仅存储 Object
元素(而不是 Image
)。如果你存储指针 - 你存储实际 class 的对象(你只是将它们存储为指向基 class 的指针)。因为没有任何内容被截断 - 您始终可以将指针转换为派生的 class 并访问其方法。
希望对您有所帮助。