【问题标题】:How to access vector in map如何访问地图中的矢量
【发布时间】:2016-05-28 04:26:38
【问题描述】:
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <cstdlib>
#include <ctime>

using namespace std;
class ship
{
    protected:
    string type;
    int size;
    int hits;
};
int main()
{
    map< char,vector<ship*> > board;
    for(int i=0;i<10;i++)
    {
        vector<ship*> v;
        for(int j = 0;j<10;j++)

        {
            ship *s = new ship();
            v.push_back(s);
        }
        board['A'+i] = v;
    }//set board 
}

我制作了map&lt;char,vector&lt;ship*&gt; &gt; 板。如何从地图中矢量的第一个元素中的第一艘船指针访问type(在ship 类中)?

【问题讨论】:

  • [c++][map][vector] 不要这样做。这就是标签的用途。
  • 首先,你不能。 type 受保护,main() 未加好友。其次,board['A'][0]-&gt;type 假设您解决了第一个问题,但我强烈怀疑是黑暗的地平线。祝你好运。
  • vector&lt;ship*&gt; v; -- 你为什么在这里使用指针?为什么不只是 vector&lt;ship&gt; v; 并跳过所有对 new 的调用?

标签: c++ dictionary vector


【解决方案1】:

好吧,也许我的回答有点过头了,我知道这并不是你真正要问的,但它可以帮助你理解为什么船舶中的价值受到保护,而且我似乎有太多时间了。

由于围绕具有共同方法和属性的船舶/怪物/对象构建游戏是一个非常常见的问题,因此有一种非常常见的方法来实现这一点。它基于三级继承。

1.界面

它将定义可以从外部调用的方法,它是一个契约。从它继承的每个类必须实现这些方法。

在你的情况下,一个基本的看起来像这样:

class IShip
{
    public:
        virtual ~IShip() // needs this, see link below
        { std::cout << "Interface destructor called" << std::endl; }

        virtual std::string type() = 0;
        virtual int         size() = 0;
        virtual int         hits() = 0;

        virtual void    specialMove() = 0;
};

Reason 用于虚拟 dtor。

2。摘要

它继承自这个接口,并实现了每艘船都可以重用的基本方法,可以这样做:

class AShip : public IShip
{
    public:
        AShip(std::string type, int size, int hits)
            : _type(type)
            , _size(size)
            , _hits(hits)
        { std::cout << "Abstract constructor called" << std::endl; }

        virtual ~AShip() // still needs this
        { std::cout << "Abstract destructor called" << std::endl; }

        virtual inline std::string type()   // inline keyword to put the code in-place instead of calling it
        { return _type; }                   // should only do this on very small methods

        virtual inline int size()           // virtual are not necessary
        { return _size; }                   // but it's best practice to clarify code

        virtual inline int hits()
        { return _hits; }

        // -- need overload method
        virtual void    specialMove() = 0;

    // -- protected since it needs to be accessible from child classes
    protected:
        std::string _type;
        int         _size;
        int         _hits;
};

此时你不能实例化任何东西,因为这两个类都是虚拟的。 More about virtual classes

接口是一个纯虚拟类(因为定义的每个方法都有'= 0')。

3.实例化

您现在可以做的是轻松实现多个继承自 AShip 但仍指定一些特殊的类,您是对的,我说的是 specialMove,我将为为了我的例子:

class TheDestructor : public AShip
{
    public:
        TheDestructor()
            : AShip("The Destructor", 20, 100)
            , _attack("DestructionOver9000")
        { std::cout << "TheDestructor constructor called" << std::endl; }

        virtual ~TheDestructor() // still needs this to help the compiler
        { std::cout << "TheDestructor destructor called" << std::endl; }

        inline void specialMove() // specialMove overload
        { std::cout << "Attack " << _attack << " from " << _type << std::endl; }

    private:
        std::string _attack;
};

class MyPunyShip : public AShip
{
    public:
        MyPunyShip()
            : AShip("My Puny Ship", 1, 1)
            , _escape("just fly away as fast as he can...")
        { std::cout << "MyPunyShip constructor called" << std::endl; }

        virtual ~MyPunyShip() // still needs this to help the compiler
        { std::cout << "MyPunyShip destructor called" << std::endl; }

        inline void specialMove() // specialMove overload
        { std::cout << _type << " " << _escape << std::endl; }

    private:
        std::string _escape;
};

现在让我们测试一下已经做了什么:

int     main()
{
    std::map<std::string, IShip*>   ships;

    ships.insert(std::make_pair("The Destructor", new TheDestructor));
    std::cout << std::endl;
    ships.insert(std::make_pair("My Puny Ship", new MyPunyShip));
    std::cout << std::endl;

    for (std::map<std::string, IShip*>::iterator itS = ships.begin() ; itS != ships.end() ; ++itS)
    {
        // *itS to access the data of the iterator
        // second to access the second member of the pair
        std::cout << "type: " << (*itS).second->type() << "\n";
        std::cout << "size: " << (*itS).second->size() << "\n";
        std::cout << "hits: " << (*itS).second->hits() << "\n";
        std::cout << std::endl;
    }

    ships["The Destructor"]->specialMove();
    ships["My Puny Ship"]->specialMove();
}

您只能调用接口中的方法,因为地图中的类型是 IShip,但它允许您实现具有不同统计数据的各种船。

让我们看看输出...

输出:

Abstract constructor called
TheDestructor constructor called

Abstract constructor called
MyPunyShip constructor called

type: My Puny Ship - size: 1 - hits: 1

type: The Destructor - size: 20 - hits: 100

Attack DestructionOver9000 from The Destructor
My Puny Ship just fly away as fast as he can...

但是,但是……有些东西不见了对吧? 有些东西似乎很奇怪......什么???我忘了用删除??

好吧,我忘了使用 c++11 作为一个整体来使示例更小,并保持我试图传达的内容清晰。我应该在这里使用std::unique_ptrstd::shared_ptr

'new' main 看起来像这样,并在启用 c++11 标志的情况下编译:

int     main()
{
    std::map<std::string, std::shared_ptr<IShip>>   ships;

    ships.emplace(std::make_pair("The Destructor", std::shared_ptr<IShip>(new TheDestructor)));
    ships.emplace(std::make_pair("My Puny Ship", std::shared_ptr<IShip>(new MyPunyShip)));

    for (auto ship : ships) // damn that's neat...
    {
        std::cout << "type: " << ship.second->type() << " - ";
        std::cout << "size: " << ship.second->size() << " - ";
        std::cout << "hits: " << ship.second->hits() << "\n";
    }

    ships["The Destructor"]->specialMove();
    ships["My Puny Ship"]->specialMove();
}

输出:

Abstract constructor called
TheDestructor constructor called

Abstract constructor called
MyPunyShip constructor called

type: My Puny Ship - size: 1 - hits: 1
type: The Destructor - size: 20 - hits: 100

Attack DestructionOver9000 from The Destructor

My Puny Ship just fly away as fast as he can...

TheDestructor destructor called
Abstract destructor called
Interface destructor called
MyPunyShip destructor called
Abstract destructor called
Interface destructor called

哇,我非常想念你 c++11。开个玩笑,你可以看到我们的 IShip* 指针会自动调用析构函数,如果你问我,这很好。

为什么接口和抽象似乎都做得过火了?我对此的看法是,一个人可能需要 IVehicle,但创建 AShip、ACar、ASpaceCraft 等......但有不同的限制。但这是一个非常有效的问题,您应该调整这种“模式”以适应您的需求和理念。

希望它能帮助你理解一些关于 c++/c++11 和继承的概念,下一步是为你构建一个factory ;)

【讨论】:

    【解决方案2】:

    由于type 被声明为protected,您通常无法访问它。 protected 成员只能由 friend 类或从该类继承的人访问。最简单的解决方案是将变量声明为public。但它有自己的警告。

    【讨论】:

      【解决方案3】:

      首先,您应该将type 声明为public

      那么,你应该做board[index].front()-&gt;type

      重要提示:index 应该是一个char 变量,因为映射board 的键的类型是char

      示例:

      #include <iostream>
      #include <string>
      #include <map>
      #include <vector>
      #include <cstdlib>
      #include <ctime>
      
      using namespace std;
      class ship
      {
          public:
          string type;
          int size;
          int hits;
      };
      int main()
      {
          map< char, vector<ship*> > board;
          for (int i = 0; i<10; i++)
          {
              vector<ship*> v;
              for (int j = 0; j<10; j++)
              {
                  ship *s = new ship();
                  s->type = "Cannon ship";
                  v.push_back(s);
              }
              board['A' + i] = v;
          }//set board 
          cout << board['A'].front()->type << endl;
      }
      

      【讨论】:

      • 这是个人喜好问题,但我更喜欢将ship 声明为struct,因为这里没有方法。那么你就不需要public 关键字了。同样在for 循环中,您可以将三行组合为:v.push_back(new ship{"Cannon ship"});
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多