英文:
How to add derived struct elements to a vector without using pointers?
问题
I'm working off of someone's code. There is a vector of struct P (Segment). I want to have different types of P. Therefore I defined struct P2 : P. But, since Segment takes just P and not P*, I cannot add element of type P2 to the Segment and use dynamic_cast since it will create a new element of type P and copy just i and I lose the name information.
我正在使用别人的代码。有一个名为 P 的结构体向量(Segment)。我想要有不同类型的 P。因此,我定义了 struct P2 : P。但是,由于 Segment 只接受 P 而不是 P*,我无法将类型为 P2 的元素添加到 Segment 中并使用 dynamic_cast,因为它将创建一个新的类型为 P 的元素,只复制 i,而我会丢失 name 信息。
What are my options here? Do I just have to change vector<P> to vector<P*> and adjust the code everywhere it's being used or create my own type Segment vector<P*> and use where I need it?
在这种情况下,我有哪些选择?我只需要将 vector<P> 更改为 vector<P*> 并在使用它的地方进行代码调整,还是需要创建自己的类型 Segment vector<P*> 并在需要时使用?
Also, why it was used vector<P> and not vector<P*> from the beginning since the vector can have hundreds and even thousands of elements?
另外,为什么一开始使用 vector<P> 而不是 vector<P*>,尽管向量可以包含数百甚至数千个元素?
英文:
I'm working off of someone's code. There is a vector of struct P (Segment). I want to have different types of P. Therefore I defined struct P2 : P. But, since Segment takes just P and not P*, I cannot add element of type P2 to the Segment and use dynamic_cast since it will create a new element of type P and copy just i and I lose the name information.
What are my options here? Do I just have to change vector<P> to vector<P*> and adjust the code everywhere it's being used or create my own type Segment vector<P*> and use where I need it?
Also, why it was used vector<P> and not vector<P*> from the beginning since the vector can have hundreds and even thousands of elements?
struct P
{
int i;
P(int i2) : i(i2) {}
}
struct P2 : P
{
string name;
P2(string name2, int i) : P(i), name(name2) {}
}
struct P3 : P
{
...
}
using Segment = vector<P>;
答案1
得分: 2
-
继承/多态性: 如你所建议的,但请使用
std::vector<std::unique_ptr<P>>,避免在现代 C++ 中使用原始指针,因为通常 vector 拥有这些对象。此外,我会定义一个合理的接口,而不是像你当前的示例中使用P2。 -
类型安全的联合: 例如,
std::variant<P,P2>,可以包含两种类型之一。然后你需要进一步定义访问者,专门处理包含的类型。 -
类型擦除: 定义一个新类作为通用接口,并将类映射到它。在最简单的版本中,它只是一个
std::function<std::string()>,可以捕获类的括号运算符等。可以将其视为无基类的继承。
可能还有其他方法,但这些是我认为最常见的方法之一。
英文:
You can basically use one of the following concepts:
-
Inheritance/Polymorphism: As you suggested, but then please with a
std::vector<std::unique_ptr<P>>. Using a raw pointer as invector<P*>is discouraged in modern C++, as the vector usually owns the objects. Moreover, I would then define a reasonable interface -- other than in your current example withP2. -
Type-safe unions: For example, a
std::variant<P,P2>, which can contain one of the two types. You then further need to define visitors which act specifically on the contained type. -
Type erasure: define a common interface as a new class and map the classes to it. In the simplest version, it's just a
std::function<std::string()>which captures, e.g., the parenthesis-operator of the classes. This can be thought of as inheritance without base classes.
There's probably more approaches, but those are imo the most common ones.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论