我如何创建一个向量的虚拟类

How can I create a vector of virtual class?

本文关键字:向量 一个 虚拟 创建 何创建      更新时间:2023-10-16

我是一个c++新手,所以我决定做一些小项目来提高自己。我尝试用类Unit和继承自Unit

的类King来编写一个简单的象棋程序。
    #include <list>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stdlib.h>     /* abs */
using namespace std;
// Each unit class represent a chess unit
class Unit{
 protected:
    int currentX;
    int currentY;
    string side;
public:
    Unit();
    Unit(string sideplay, int Xpos,int Ypos)
    {
         currentX=Xpos; currentY= Ypos;side=sideplay;
    }
    int getX()
    {
        return currentX;
    }
    int getY()
    {
        return currentY;
    }
    string getside()
    {
        return side;
    }
    void setpos(int newX,int newY)  //set new position
    {
        currentX=newX;
        currentY=newY;
    }

     bool validmove(vector<Unit> unitlist ,string sidepick,int Xpos,int Ypos)
     {   int i=0;
         while(i != 3)
         {   int X=unitlist[i].getX();
             int Y=unitlist[i].getY();
             string sidetemp= unitlist[i].getside();
             if ((X==Xpos)&&(Y==Ypos)&&(sidetemp==sidepick))
             {
                 return false;
             }
             else if ((X==Xpos)&&(Y==Ypos)&&(sidetemp!=sidepick))
             {   //unitlist[i]=NULL;
                 return true;
             }
                 i++;
     }
         return true;

     }
     virtual void moveunit(vector<Unit> unitlist ,int nextX,int nextY);


};

class King: public Unit{
    public:
    King(string sideplay, int Xpos,int Ypos):Unit(sideplay,Xpos,Ypos)
    {}
     void moveunit(vector<Unit> unitlist ,int nextX,int nextY){
        int diffX=abs(nextX-currentX);
        int diffY=abs(nextY-currentY);
        if ((diffX==1)||(diffY==1))
        {   if (validmove(unitlist,side,nextX,nextY))
            {
            setpos(nextX,nextY);}
            }
}
}; 

下面是我的main:

int main()
{
    vector<Unit> chessunit;
    chessunit.push_back(King("white",3,1));
    chessunit.push_back(King("black",3,2));
    chessunit.push_back(King("white",4,1));
    if (chessunit[0].validmove(chessunit,"white",3,2))
    {
        cout<<"hehe"<<endl;
    }
    chessunit[0].moveunit(chessunit,3,2);
    int k= chessunit[0].getY();
    cout<<k<<endl;

    return 0;
}

我一直得到LNK 2001错误:我的虚拟方法"moveunit"的未解决的外部符号。

解决您的问题的最简单的方法是使用指针或智能指针:存储vector<Unit*>, vector<std::shared_ptr<Unit>>vector<std::unique_ptr<Unit>>(感谢@rubenvb)而不是vector<Unit>,然后添加您的国王像这样:

myVector.push_back(new King...); // or
myVector.push_back(std::shared_ptr<King>(new King...)); // or
myVector.push_back(std::unique_ptr<King>(new King...));

为什么?

如果你分配了一个虚拟类的对象(例如Unit unit),并且你想给它分配一个该类实现的对象,例如:

Unit unit;
unit = King(...);

那么你会得到一个错误,或者至少会遇到麻烦,除非你为Unit提供了一个构造函数,将King作为参数,或者提供了一个足够的move操作符。这是因为如果你试图将一个类型不是Unit的对象分配给unit,编译器和/或运行时(取决于你的编译器的后端是什么)将很难弄清楚这些类型是如何兼容的,如果事情"不适合"内存,该怎么办,以及如何处理内存布局问题。

进一步阅读

    有关指针与智能指针的更多信息,请考虑这个线程。这里还有一个相关的Stackoverflow问题和一篇关于使用shared_ptr与STL集合的文章在这个线程中可以找到更多关于尝试"挤压"一种类型的对象到另一种类型(称为切片)的信息。

你现在面临的问题是由于切片:当你添加一个King到向量,它被切片成一个Unit的实例。

解决这个问题的一种方法是将chessunit转换为std::shared_ptr<Unit>的向量,并在堆上分配单元。

注:由于没有定义Unit::moveunit(),因此将其设置为纯虚的:

 virtual void moveunit(vector<Unit> unitlist ,int nextX,int nextY) = 0;
                                                                   ^^^