【问题标题】:How do I supply parameters to a constructor called by another constructor?如何为另一个构造函数调用的构造函数提供参数?
【发布时间】:2025-12-05 00:35:01
【问题描述】:

在我的项目中,我有四个结构:NodeRingDiscGraph

  • 一个Ring 包含两个向量,每个向量有12 个Nodes
  • 一个Disc包含一个Rings的向量(一个参数告诉构造函数有多少)
  • Graph 包含Discs 的向量(同样,数字由参数提供)

Graphs 外,一切正常。如果我想构造一个Disc,我允许通过构造函数设置它包含在其std::vector<Ring> rings 中的Rings 的数量,如下所示:

Disc::Disc(size_t r) : rings {r} {};

但是如果我想构建一个图表,我需要以某种方式设置 both 圆盘的数量每个圆盘中的环数。所以我想我需要的是一种在 Ring 构造函数被调用时为每个正在构造的 Disc 输入参数的方法。我是编程新手,不幸的是,我找不到任何关于如何告诉构造函数在这种情况下该做什么的教程。但也许我以完全错误的方式处理这个问题。

【问题讨论】:

  • 所以,你基本上有类似this?
  • @TedLyngmo 是的,差不多就是这样。目前我并不担心向量项的任何成员的值,只关心每个 Ring/Disc/Graph 中有多少。

标签: c++ class oop struct constructor


【解决方案1】:

我可以使用与您存储在类中的相同类型的容器直接初始化您的每个类。这样您就不必提供它们中的每个有多少。

这里是你的课程的一些编造版本。

struct Node { int x; };

struct Ring {
    Ring(std::array<std::array<Node, 12>, 2> a) : nodes(std::move(a)) {}
    auto begin() { return nodes.begin(); }
    auto end() { return nodes.end(); }
private:
    std::array<std::array<Node, 12>, 2> nodes;
};

struct Disc {
    Disc(std::vector<Ring> in) : rings(std::move(in)) {}
    auto begin() { return rings.begin(); }
    auto end() { return rings.end(); }
private:
    std::vector<Ring> rings;
};
 
struct Graph {
    Graph(std::vector<Disc> in) : discs(std::move(in)) {}
    auto begin() { return discs.begin(); }
    auto end() { return discs.end(); }
private:
    std::vector<Disc> discs;
};

如果您愿意,您可以一次性创建一个完整的 Graph 对象

Graph graph(
    { // discs
        { // disc 0
            { // rings
                { // ring 0
                    { // array initialization
                        { // outer array
                            { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12}, // nodes 0 (inner)
                            {13,14,15,16,17,18,19,20,21,22,23,24}  // nodes 1 (inner)
                        }
                    }
                },
                { // ring 1
                    {
                        {
                            {25,26,27,28,29,30,31,32,33,34,35,36},
                            {37,38,39,40,41,42,43,44,45,46,47,48}
                        }
                    }
                }
            }
        },
        { // disc 1
            { // rings
                { // ring 0
                    {
                        {
                            {49,50,51,52,53,54,55,56,57,58,59,60},
                            {61,62,63,64,65,66,67,68,69,70,71,72}
                        }
                   }
                }
            }
        }
    }
);

Demo

【讨论】:

  • 谢谢,这很有用。当我在项目上构建时,我会考虑类似的实现。
【解决方案2】:

向量是灵活的,它们可以被构造成空的,然后填充。

在你的场景中,你会做这样的事情。

Graph::Graph(size_t nDiscs, size_t *nRingsPerDisc) : discs{}
{
    for(int i = 0; i < nDiscs; i++)
        discs.push_back(Disc(RingsPerDisc[i]));
}

【讨论】:

  • 我可能做错了,但我无法编译
  • @slynt 你得到什么样的编译错误?
【解决方案3】:

我刚刚想出了一个似乎效果很好的解决方案。为了便于记录,这是我现在给 Graph 构造函数的定义:

Graph::Graph(size_t d, size_t r) : discs (d, *new Disc {r}) {};

【讨论】:

  • 这似乎有效,但几乎绝对不是您想要的。您用完全相同的光盘的d 副本填充discs,然后您不删除该原始光盘(每次对new 的调用都应该在某个时间点之后调用delete)但是,如果您希望图表中的所有圆盘大小相同,这最直接的方法,只是不要在这里使用operator new。简单地写: discs(d, Disc{r}) {} 应该可以工作,没有任何副作用。