【问题标题】:How can I create objects while adding them into a vector?如何在将对象添加到向量中时创建对象?
【发布时间】:2013-04-04 03:26:46
【问题描述】:

我有一个 C++ 向量。我希望向量包含可变数量的对象。

Visual Studio 2012 给我一个错误:

Error: type name is not allowed

从此 C++ 代码:

#include <iostream>
#include <vector>
using namespace std;

class testObject{
private:
   int someInt;
public:
   testObject(int a){ someInt=a; }
   void show() { cout<<someInt<<endl; }
};

int main()
{
    vector<testObject> testVector;
    cout << "Initial size: " << testVector.size() <<endl;

    for ( int i = 0; i < 3; i++ )
        testVector.push_back(testObject(3));
    cout << "New size: " << testVector.size() << endl;

    for ( int j = 0; j < 3; j++ )
        testVector[ j ].show();

    system("pause");
}    

但这是另一个看起来相同但不起作用的代码示例。

void Dealer::setNumberOfPlayers( const int tNumber )
{
    for ( int i = 0; i < tNumber; i++ )
        vectorOfGamers.push_back(Player); // Player is a class that I created
}

我可以创建向量来同时保存 Dealer、Bot 和 Player 的对象吗?我怎么做?据我所知,vector 中的所有对象都应该是一种类型。

【问题讨论】:

  • +1 提出一个恰当的问题(你的英语很好)。
  • 创建一个 Player 实例。
  • 重复但是,这两个问题的答案都可以通过谷歌轻松找到,甚至可以在 SO 上找到。
  • 在问这个问题之前我真的用谷歌搜索过。也许我的搜索关键字不够准确:(。

标签: c++


【解决方案1】:

要回答您问题的第一部分,您必须先创建一个 Player 类型的对象,然后才能使用它。当您说 push_back(Player) 时,它的意思是“将 Player class 添加到向量中”,而不是“将 Player 类型的对象添加到向量中”(这就是您的意思)。

您可以像这样在堆栈上创建对象:

Player player;
vectorOfGamers.push_back(player);    // <-- name of variable, not type

或者您甚至可以内联创建一个临时对象并将其推送(将其放入向量中时会被复制):

vectorOfGamers.push_back(Player());    // <-- parentheses create a "temporary"

回答第二部分,你可以创建一个基本类型的向量,这将允许你推回任何子类型的对象;但是,这不会按预期工作:

vector<Gamer> gamers;
gamers.push_back(Dealer());    // Doesn't work properly!

因为当庄家对象被放入向量时,它被复制为作为玩家对象——这意味着只有玩家部分被有效地“切片”对象复制。但是,您可以使用指针,因为那时只会复制指针,并且永远不会对对象进行切片:

vector<Gamer*> gamers;
gamers.push_back(new Dealer());    // <-- Allocate on heap with `new`, since we
                                   // want the object to persist while it's
                                   // pointed to

【讨论】:

  • @eoLithic:它在第一个示例中起作用,因为它正在创建一个临时对象(“t​​ype(constructor-arguments)”语法)并将其传入;尽管语法相似,但含义却截然不同;-)
  • 是否可以在堆上分配最后一部分(并且仍然具有多态性)?
  • @mtahmed:嗯,从技术上讲,它不必在堆上分配——事实上,它是通过一个指针访问的,这使它有可能实现多态性(同时无需切片即可复制) .您也可以获取分配在堆栈上的对象的地址 - 但您必须小心仅在它们被销毁之前使用它们(当然也适用于堆分配的对象,但意外销毁更难在你用完之前的那些)。
  • 我明白了。我还想问的是是否有可能在没有切片的情况下推回一个对象......是否有一些巧妙的技巧可以在不进行显式分配(或使用指向易失性堆栈上的对象的指针)的情况下实现这一点。
  • @mtahmed:不,抱歉。当您将对象添加到矢量时,它会创建一个模板类型的新对象(通过放置在现场,或者复制或移动您给它的对象)。不管它是如何完成的,对象只有它自己的成员的空间(对象的大小是在编译时计算的,记住),而不是继承类的任何成员,所以派生对象会被切片。 (至于虚方法,它们也将无法访问,因为 vtable 将用于错误的(基本)类型。)
【解决方案2】:

问题一:

   vectorOfGamers.push_back(Player)

这是有问题的,因为您不能直接将类名推送到向量中。 您可以将类的对象推送到向量中,也可以将引用或指向类类型的指针推送到向量中。例如:

vectorOfGamers.push_back(Player(name, id)) 
  //^^assuming name and id are parameters to the vector, call Player constructor
  //^^In other words, push `instance`  of Player class into vector

问题 2:

These 3 classes derives from Gamer. Can I create vector to hold objects of Dealer, Bot and Player at the same time? How do I do that?

是的,你可以。您可以创建指向基类Gamer 的指针向量。 一个不错的选择是使用smart_pointer的向量,因此,您不需要自己管理指针内存。由于其他三个类都是从Gamer派生的,基于多态性,可以将派生类对象赋值给基类指针。您可以从这篇文章中找到更多信息:std::vector of objects / pointers / smart pointers to pass objects (buss error: 10)?

【讨论】:

    【解决方案3】:

    您不能将 class 插入到向量中,但可以插入类的 object(前提是它是正确的类型或可转换的)。 p>

    如果Player 类型有默认构造函数,您可以通过Player() 创建一个临时对象,这应该适用于您的情况:

    vectorOfGamers.push_back(Player());
    

    【讨论】:

      【解决方案4】:

      我知道线程已经全部完成,但是当我检查通过时,我想出了一个解决方案(下面列出的代码)。希望对您有所帮助。

      #include <iostream>
      #include <vector>
      
      class Box
      {
          public:
      
          static int BoxesTotal;
          static int BoxesEver;
          int Id;
      
          Box()
          {
              ++BoxesTotal;
              ++BoxesEver;
              Id = BoxesEver;
              std::cout << "Box (" << Id << "/" << BoxesTotal << "/" << BoxesEver << ") initialized." << std::endl;
          }
      
          ~Box()
          {
              std::cout << "Box (" << Id << "/" << BoxesTotal << "/" << BoxesEver << ") ended." << std::endl;
              --BoxesTotal;
          }
      
      };
      
      int Box::BoxesTotal = 0;
      int Box::BoxesEver = 0;
      
      int main(int argc, char* argv[])
      {
          std::cout << "Objects (Boxes) example." << std::endl;
          std::cout << "------------------------" << std::endl;
      
          std::vector <Box*> BoxesTab;
      
          Box* Indicator;
          for (int i = 1; i<4; ++i)
          {
              std::cout << "i = " << i << ":" << std::endl;
              Box* Indicator = new(Box);
              BoxesTab.push_back(Indicator);
              std::cout << "Adres Blowera: " <<  BoxesTab[i-1] << std::endl;
          }
      
          std::cout << "Summary" << std::endl;
          std::cout << "-------" << std::endl;
          for (int i=0; i<3; ++i)
          {
              std::cout << "Adres Blowera: " <<  BoxesTab[i] << std::endl;
          }
      
          std::cout << "Deleting" << std::endl;
          std::cout << "--------" << std::endl;
          for (int i=0; i<3; ++i)
          {
              std::cout << "Deleting Box: " << i+1 << " (" <<  BoxesTab[i] << ") " << std::endl;
              Indicator = (BoxesTab[i]);
              delete(Indicator);
          }
      
          return 0;
      }
      

      它产生的结果是:

      Objects (Boxes) example.
      ------------------------
      i = 1:
      Box (1/1/1) initialized.
      Adres Blowera: 0xdf8ca0
      i = 2:
      Box (2/2/2) initialized.
      Adres Blowera: 0xdf8ce0
      i = 3:
      Box (3/3/3) initialized.
      Adres Blowera: 0xdf8cc0
      Summary
      -------
      Adres Blowera: 0xdf8ca0
      Adres Blowera: 0xdf8ce0
      Adres Blowera: 0xdf8cc0
      Deleting
      --------
      Deleting Box: 1 (0xdf8ca0) 
      Box (1/3/3) ended.
      Deleting Box: 2 (0xdf8ce0) 
      Box (2/2/3) ended.
      Deleting Box: 3 (0xdf8cc0) 
      Box (3/1/3) ended.
      

      【讨论】:

        【解决方案5】:
        // create a vector of unknown players.
        std::vector<player> players;
        
        // resize said vector to only contain 6 players.
        players.resize(6);
        

        值总是被初始化的,所以一个包含 6 个玩家的向量就是一个包含 6 个有效玩家对象的向量。

        至于第二部分,你需要使用指针。 Instantiating c++ interface as a child class

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-14
          相关资源
          最近更新 更多