【问题标题】:C++ Class initializedC++ 类初始化
【发布时间】:2013-10-01 12:42:54
【问题描述】:

C++ 和类

我有一个名为“Sprite”的类,当它被初始化时,它需要一个 bool 变量:

// constructor
Sprite::Sprite(bool type)
{ 
   // set stuff
}

// two Sprites of different types
Sprite Hero(1) 
Sprite Enemy(0)

问。如何初始化一个包含 100 个 0 类型 Sprite 的数组?

精灵敌人[100] ?

【问题讨论】:

标签: c++ class


【解决方案1】:

我的建议是您使用std::vector,然后使用constructor 获取值参数。

喜欢

std::vector<Sprite> Enemies(100, Sprite(false));

您可能需要为Sprite 定义适当的复制构造函数和复制赋值运算符才能使其工作。


如果您没有向量(或std::array,在您的情况下可能会更好),那么您必须将数组声明为普通数组,然后使用循环初始化每个条目:

Sprite Enemies[100];
for (size_t i = 0; i < 100; ++i)
    Enemies[i].set(false);

【讨论】:

  • 非常感谢 - 这实际上是针对 Arduino 项目的,但不确定 Arduino 是否有向量 - 我看到有人自己写了:forum.arduino.cc/index.php/topic,45626.0.html 虽然不是我想要的东西
  • @JakeFrench 如果您使用的是符合标准的 C++ 编译器,则应该有向量。
  • 只使用简单的 Arduino 草图
  • @NeilKirk 有时在嵌入式处理器上,由于空间限制,项目是使用-nostdlib 构建的,因此默认情况下没有可用的容器。
  • @RedX 啊,有趣。但是,如果是这种情况,那么问题应该被标记为“嵌入式”或其他。
【解决方案2】:

您可以使用默认构造函数,它会简单地默认为 0 值,如下所示:

//default constructor
Sprite::Sprite()
{ 
  //set to false 
}

Sprite::Sprite(bool type)
{ 
   // set to type
}

现在 精灵敌人[100] 会工作

或者使用更少的代码在构造函数中使用默认值,如下所示:

Sprite::Sprite(bool type=false)
{
     //set to type
{

【讨论】:

  • 如果您需要将它们全部设置为 true,您可以使用类似 std::fill(Enemies, Enemies+100, Sprite(1)); 的内容。
  • 您应该使用初始化列表而不是在构造函数主体中设置。
【解决方案3】:

除非我错了,否则您不能直接将构造函数与对象数组的参数一起使用。一种解决方案是使用std::vector

std::vector<Sprite> Ennemies(100, Sprite(false));
std::vector<Sprite> Ennemies(100, {false}); // C++11 style

如果你真的想要 C 风格的数组,你可以通过一个例子得到它:

Sprite* pEnnemies = &Ennemies.front();

另一种解决方案是使用新的 C++11 容器 std::array,它只是 STL 语法中的 C 样式数组:

std::array<Sprite, 100> Ennemies(Sprite(false));

【讨论】:

  • 如果你要使用 C++11 风格,你也应该为 std::vector 构造函数使用大括号。 :)
【解决方案4】:

创建类数组时,必须由默认构造函数创建。

您可以为您的类型参数添加一个默认值“= false”,然后代码就可以工作了。但它不是很灵活,因为您可能需要其他类型的数组。

另一种方法是让您的精灵在使用不同类型构建后重置。创建空白精灵数组后,在 for 循环中对它们调用 reset(type)。

如果您确实需要在元素上使用非默认构造函数,请使用 std::vector。有两种方法可以做到。

std::vector<Sprite> Enemies;
Enemies.reserve(100);
for (int i = 0; i < 100; i++)
{
    Enemies.push_back(Sprite(0));
}

std::vector<Sprite> Enemies(100, Sprite(0));

【讨论】:

    【解决方案5】:

    为了完整起见,还有最后一种方法使用placement-new

    unsigned char data[sizeof(Sprite) * 100];
    Sprite* ptr = reinterpret_cast<Sprite*>(&data[0]);
    Sprite* end = ptr + 100;
    for (; ptr != end; ++ptr)
        new (ptr) Sprite(0);
    

    这几乎就是其他不依赖复制构造函数在内部使用的答案。

    如果Sprite 有一个重要的析构函数,您将不得不在data 的生命周期结束时使用另一个循环显式调用它:

    Sprite* ptr = reinterpret_cast<Sprite*>(&data[0]);
    Sprite* end = ptr + 100;
    for (; ptr != end; ++ptr)
        ptr->~Sprite();
    

    【讨论】:

      【解决方案6】:

      非常感谢大家的关注,在阅读了 cmets 之后,我发现这是可行的,重载了构造函数:

      class Sprite
      {
        public:
          Sprite();
          Sprite(bool type);
          void Move();
        private:
          unsigned int x, y, Ammo;
          bool Alive;
          bool Type;
      };
      
      // constructor
      Sprite::Sprite()
      {
        Alive = true;
        Type  = 0;
        Ammo  = 25;
        x = random(0, 82);
        y = random(0, 20);
      }
      
      Sprite::Sprite(bool type)
      {
        Alive = true;
        Type  = 1;
        Ammo  = 25;
        x = 20; // get x from btn press
        y = 10; // get y from btn press
      } 
      

      精灵英雄(1); 精灵敌人[100];

      【讨论】:

      • 这不是怎么做的。请参阅我的答案以重写您的构造函数。
      【解决方案7】:

      使用默认参数:

      Sprite::Sprite(bool type=false) : mymember(type)
      {}
      

      然后当你声明时:

      Sprite Enemies[100];
      

      它将调用所有 100 个元素的默认 ctor。

      您应该了解成员初始化器列表,在 C++ 中编写构造函数的正确方法是:

      Sprite(bool type=false); // declaration
      
      ...
      Sprite::Sprite(bool type) :  // definition
        x(random(0, 82)), 
        y(random(0, 20)),
        Ammo(25),
        Alive(true),
        Type(type)
      {}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-17
        • 2020-08-19
        • 2015-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多