[英]How to access derived objects in base class container without direct inheritance
I know I can cast pointer to base class in a container to pointer to derived class with the help of static_cast<derived_class*>(base_class_ptr)
. 我知道我可以在static_cast<derived_class*>(base_class_ptr)
的帮助下将指向基础类的 指针转换为指向派生类的容器。
However what can I do if they are not directly related, but only have a common child. 但是,如果他们没有直接关系,但只有一个普通的孩子,该怎么办。 Look at the following example: 看下面的例子:
#include <iostream>
#include <string>
#include <vector>
#include <memory>
class Item
{
public:
Item(std::string name): _name(name) { /* */ };
private:
std::string _name;
};
class Readable
{
public:
Readable(std::string content): _content(content) { /* */ };
virtual auto content(void) const -> std::string
{
return this->_content;
}
private:
std::string _content;
};
class Book: public Item, public Readable
{
public:
Book(std::string name, std::string content): Item(name), Readable(content) { /* */ };
};
class Person
{
public:
auto read(const Readable& readable) const noexcept
{
std::cout << readable.content() << '\n';
}
};
int main(void)
{
auto i0 = std::make_unique<Item>("Pot");
auto i1 = std::make_unique<Item>("Shoe");
auto b0 = std::make_unique<Book>("Death of a Salesman", "Blablablabla...");
std::vector<std::unique_ptr<Item>> container;
container.emplace_back(std::move(i0));
container.emplace_back(std::move(i1));
container.emplace_back(std::move(b0));
Person jonnie{};
jonnie.read(static_cast<Readable*>(container[2].get())) // Error!
}
I want to read a Book
from the Item
s container, and that should be ok, because it is inherits from Readable
, but I can't, because the compiler complains: 我想从Item
的容器中读取一Book
,这应该没问题,因为它是从Readable
继承的,但是我不能,因为编译器抱怨:
static_cast from 'pointer' (aka 'Item *') to 'Readable *', which are not related by inheritance, is not allowed
What can I do in such a case? 在这种情况下我该怎么办? Is there a clean solution? 有没有干净的解决方案?
You are looking to cast objects around that are required to be polymorphic ; 您正在寻找围绕需要多态的对象 ; they require a virtual method. 他们需要虚拟方法。 The easiest (and I think in this case the best) is to make the destructor virtual
for all the base classes, eg; 最简单的方法(我认为在这种情况下最好)是使所有基本类的析构函数都是virtual
的,例如:
class Item
{
public:
virtual ~Item() { /* */ };
// .. the rest of the class
};
This allows dynamic_cast<>
to work at runtime (it works with polymorphic types), it will check for and cast the object appropriately. 这允许dynamic_cast<>
在运行时运行(与多态类型一起使用),它将检查并正确地转换对象。 One caveat here (given the sample use in the OP) is that you will almost certainly have to check the return value against nullptr
to check the cast succeeded. 这里的一个警告(考虑到OP中的示例用法)是,几乎可以肯定,您必须对照nullptr
检查返回值以检查是否成功进行了nullptr
转换。
If you want to read a Book
, you should cast it to a Book
(which is derived from Item
). 如果您想阅读一Book
,则应将其转换为一Book
(从Item
派生)。
The Book
can then be used as a Readable
, beacuse it is . 该Book
则可以作为一个Readable
,怎么一回事,因为它是 。 But the Item
is not. 但Item
不是。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.