如何将派生结构元素添加到向量中而不使用指针?

huangapple go评论56阅读模式
英文:

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 in vector<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 with P2.

  • 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.

huangapple
  • 本文由 发表于 2023年5月25日 04:01:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76327027.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定