Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
虚拟关键字似乎被忽略了 这是我的第一个“大”C++项目,我被卡住了。我试图创建一个简单的ASCII流氓。我有一个角色类,由玩家类和怪物类继承。怪物类由吸血鬼和狼人类继承_C++_Inheritance_Polymorphism - Fatal编程技术网

虚拟关键字似乎被忽略了 这是我的第一个“大”C++项目,我被卡住了。我试图创建一个简单的ASCII流氓。我有一个角色类,由玩家类和怪物类继承。怪物类由吸血鬼和狼人类继承

虚拟关键字似乎被忽略了 这是我的第一个“大”C++项目,我被卡住了。我试图创建一个简单的ASCII流氓。我有一个角色类,由玩家类和怪物类继承。怪物类由吸血鬼和狼人类继承,c++,inheritance,polymorphism,C++,Inheritance,Polymorphism,在GameSystem类的startName函数中,我将怪物数组的每个元素(应该充满吸血鬼和狼人对象)提交给moveAround函数。吸血鬼、狼人和怪物都有这个功能,但只有怪物移动功能被访问。如果你注意到在下面的代码中,我在Monster类中提供了virtual关键字 这让我觉得我在用子类填充怪物数组时搞砸了。在游戏系统构造器中,我通过随机确定怪物阵列中的特定元素是狼人还是吸血鬼来实现这一点 我使用代码块,在编译方面,我有g++遵循C++11 GameSystem.cpp #include &l

在GameSystem类的startName函数中,我将怪物数组的每个元素(应该充满吸血鬼和狼人对象)提交给moveAround函数。吸血鬼、狼人和怪物都有这个功能,但只有怪物移动功能被访问。如果你注意到在下面的代码中,我在Monster类中提供了virtual关键字

这让我觉得我在用子类填充怪物数组时搞砸了。在游戏系统构造器中,我通过随机确定怪物阵列中的特定元素是狼人还是吸血鬼来实现这一点

我使用代码块,在编译方面,我有g++遵循C++11

GameSystem.cpp

#include <iostream>
#include <string>
#include "GameSystem.h"
#include "Map.h"
#include "Player.h"
#include "Werewolf.h"
#include "Vampire.h"
#include "conio.h"
#include <cstdio>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <time.h>

GameSystem::GameSystem(string mapName){

    srand (time(NULL));

    _map.load(mapName);

    _map.obtainSpawningLocations(_player.getToken(),_player);

    Werewolf werewolf;
    Vampire vampire;

for(int i = 0; i < 5; i++){

    _spawnValue = rand() % 2;   //We generate either 1 or 2

    if(_spawnValue==1){

        _theMonsters[i] = werewolf;
        cout<<"Werewolf"<<endl;
    }
    else{
        _theMonsters[i] = vampire;
        cout<<"Vampire"<<endl;
    }
    _map.obtainSpawningLocations(_theMonsters[i].getToken(),_theMonsters[i]);
}
}
void GameSystem::startGame(){
bool isOver = false;
    while(isOver!=true){

        _map.print();
        movePlayer();
        for(int i = 0; i <5; i++){
        _theMonsters[i].moveAround(); //prints out Monster.moveAround()
        //I need it to print out Vampire.moveAround() and //Werewolf.moveAround

        }

       }
}

void GameSystem::movePlayer(){
    char input;
    input = getch();
    string clearScreenString(100,'\n'); //Prints out a newLine char 100 times
    cout << clearScreenString;
    _map.checkMovement(input, _player);
}


char GameSystem::getch(){

    char buf=0;
    struct termios old={0};
    fflush(stdout);
    if(tcgetattr(0, &old)<0)
        {perror("tcsetattr()");}
    old.c_lflag&=~ICANON;
    old.c_lflag&=~ECHO;
    old.c_cc[VMIN]=1;
    old.c_cc[VTIME]=0;
    if(tcsetattr(0, TCSANOW, &old)<0)
        {perror("tcsetattr ICANON");}
    if(read(0,&buf,1)<0)
        {perror("read()");}
    old.c_lflag|=ICANON;
    old.c_lflag|=ECHO;
    if(tcsetattr(0, TCSADRAIN, &old)<0)
        {perror ("tcsetattr ~ICANON");}
    //printf("%c\n",buf);
    return buf;
 }
Player.h

#pragma once
#include <string>
#include "Character.h"
using namespace std;

class Player : public Character {

public:
    Player();  

protected:
    int _x;
    int _y;
    char _token = '@';
};

在_theMonsters[i].moveAround()上没有发生虚拟调度。您需要有一个指向monster类型对象的指针数组。事实上,在尝试设置类层次结构的方式中存在很多问题,例如,在派生类中有同名的成员变量。

在_theMonsters[i].moveAround()上没有发生虚拟调度。您需要有一个指向monster类型对象的指针数组。事实上,在设置类层次结构的方法中存在很多问题,例如,在派生类中有同名的成员变量。

这里有几个问题

  • 怪物::_令牌
    狼人::_令牌
    ,吸血鬼::_令牌都是不同的变量。一个
    狼人
    对象既有
    怪物::\u标记
    又有
    狼人::\u标记
  • Monster\u theMonsters[5]
    是由5个
    Monster
    对象组成的数组。它永远不会是吸血鬼或狼人,永远是怪物。由于对象将始终是相同类型的:
    Monster
    ,因此不需要执行虚拟调度

  • 虚拟分派仅适用于指针和引用。要实现这一点,您需要使用指向
    Monster
    s:
    Monster*\u theMonsters[5]
    的指针数组。然后你可以像
    \u theMonsters[i]=new Vampire()
    那样填充它。如果这样做,您需要记住在处理完对象后删除对象,或者可以使用智能指针,如
    std::unique\u ptr
    std::shared\u ptr
    而不是原始的
    Monster*
    s。这里有几个问题

  • 怪物::_令牌
    狼人::_令牌
    ,吸血鬼::_令牌都是不同的变量。一个
    狼人
    对象既有
    怪物::\u标记
    又有
    狼人::\u标记
  • Monster\u theMonsters[5]
    是由5个
    Monster
    对象组成的数组。它永远不会是吸血鬼或狼人,永远是怪物。由于对象将始终是相同类型的:
    Monster
    ,因此不需要执行虚拟调度

  • 虚拟分派仅适用于指针和引用。要实现这一点,您需要使用指向
    Monster
    s:
    Monster*\u theMonsters[5]
    的指针数组。然后你可以像
    \u theMonsters[i]=new Vampire()
    那样填充它。如果你这样做,你需要记住在处理完对象后删除它们,或者你可以使用智能指针,比如
    std::unique_ptr
    std::shared_ptr
    而不是原始的
    Monster*
    s.

    考虑到你的建议,我把Monster*_monsters指针放到了[5];在游戏系统中。我还修改了GameSystem构造函数中的for循环,使其具有
    \u monsterPointers[I]=new Werewolf()吸血鬼也是如此。但是,这不允许我在收到此错误时调用
    obtainspawinglocations
    :没有匹配的函数用于调用Map::obtainspawinglocations(char,Monster*&)。我如何减轻这种影响?是创建接受这些参数的非常相似的函数的唯一选项吗?只需像调用
    \u map一样调用它。获取生成位置(\u theMonsters[i]。getToken(),*\u theMonsters[i])考虑到你的建议,我把怪物*_怪物指针[5];在游戏系统中。我还修改了GameSystem构造函数中的for循环,使其具有
    \u monsterPointers[I]=new Werewolf()吸血鬼也是如此。但是,这不允许我在收到此错误时调用
    obtainspawinglocations
    :没有匹配的函数用于调用Map::obtainspawinglocations(char,Monster*&)。我如何减轻这种影响?是创建接受这些参数的非常相似的函数的唯一选项吗?只需像调用
    \u map一样调用它。获取生成位置(\u theMonsters[i]。getToken(),*\u theMonsters[i])获取繁殖位置
    已经使用了一个
    字符&
    ,就多态性而言,这很好。如果切换到使用指针数组,则需要取消对它们的引用以将它们传递到
    获取繁殖位置
    \u map.获取繁殖位置(\u theMonsters[i]->getToken(),*\u theMonsters[i])#include <string>
    #include "Character.h"
    
    using namespace std;
    
    
    Character::Character(){
    
    }
    
    
    char Character::getToken(){
    return _token;
    }
    
    void Character::setLocation(int x, int y){
    _x = x;
    _y = y;
    }
    
    void Character::getLocation(int &x, int &y){
    x = _x;
    y = _y;
    }
    
    #pragma once
    #include <string>
    
    class Character{
    
    public:
        Character();
    
        char getToken();
        void setLocation(int x, int y);
        void getLocation(int &x, int &y);
    
    protected:
        int _x;
        int _y;
        char _token = '!';
    };
    
    #include <iostream>
    #include <vector>
    #include <stdlib.h>
    #include <string>
    #include <fstream>
    #include <cstring>
    #include <random>
    #include <ctime>
    #include <tuple>
    #include "Map.h"
    #include <time.h>
    
    Map::Map(){
    srand (time(NULL));
    }
    
    void Map::load(string levelName){
        ifstream theStream;
        theStream.open(levelName);
    
        if(theStream.fail()){
            perror(levelName.c_str());
            system("PAUSE");
            exit(1);
        }
    
        string line;
        while(getline(theStream, line)){
        _mapData.push_back(line);
        }
            theStream.close();
    
    }
    
    void Map::obtainSpawningLocations(char characterToken,Character &_character){
    /*
    Below code provides all the possible spawning locations for the player
    and stores them in an array of tuples.
    */
    
    tuple<int,int> myTuple[600];    //Hard coded 600 value is messy.  Change later
    
    int numberOfSpawnPoints = 0;
    int upperLimitForNumberGenerator = 0;
    /*
    The for loop below records all of the possible spawning locations and stores them in the tuple array
    */
        for(int i = 0; i<_mapData.size();i++){
            for(int j = 0; j<_mapData[i].size();j++){
                if(_mapData[i][j]=='.'){
                        get<0>(myTuple[numberOfSpawnPoints]) = j;
                        get<1>(myTuple[numberOfSpawnPoints]) = i;
                        numberOfSpawnPoints++;
                        }
                    }
        }
    upperLimitForNumberGenerator = numberOfSpawnPoints;
    
    int characterCoordinates = rand()%upperLimitForNumberGenerator;
    
    int xCoordinate = get<0>(myTuple[characterCoordinates]);
    int yCoordinate = get<1>(myTuple[characterCoordinates]);
    
    _mapData[yCoordinate][xCoordinate] = characterToken;   //Remember y is first and x is second
    
    _character.setLocation(xCoordinate, yCoordinate);
    }
    
    void Map::print(){
        for(int i=0;i<_mapData.size(); i++){
            printf("%s\n", _mapData[i].c_str());
        }
        printf("\n");
    }
    
    void Map::checkMovement(char input, Player &aPlayer){ 
    
    int x;
    int y;
    
    aPlayer.getLocation(x,y);
    
    char aLocation;
    
     switch(input) {
        case 'w':
        case 'W':   //If 1 up from the player token is a '.' then we move him up
                    //via a different function
                    //Otherwise we do nothing.
    
                    aLocation = returnLocation(x,y-1);
                    if(aLocation == '.'){
                    _mapData[y][x] = '.';
                    _mapData[y-1][x] = '@';
                    aPlayer.setLocation(x,y-1);
                    }
                    else
                    cout<<"Can't go here!"<<endl;
            break;
    
    
    
    
        case 'a':
        case 'A':
                    aLocation = returnLocation(x-1,y);
                    if(aLocation == '.'){
                    _mapData[y][x] = '.';
                    _mapData[y][x-1] = '@';
                    aPlayer.setLocation(x-1,y);
                    }
                    else
                    cout<<"Can't go here!"<<endl;
            break;
        case 's':
        case 'S':
    
                    aLocation = returnLocation(x,y+1);
                    if(aLocation == '.'){
                    _mapData[y][x] = '.';
                    _mapData[y+1][x] = '@';
                    aPlayer.setLocation(x,y+1);
                    }
                    else
                    cout<<"Can't go here!"<<endl;
            break;
        case 'd':
        case 'D':
                    aLocation = returnLocation(x+1,y);
                    if(aLocation == '.'){
                    _mapData[y][x] = '.';
                    _mapData[y][x+1] = '@';
                    aPlayer.setLocation(x+1,y);
                    }
                    else
                    cout<<"Can't go here!"<<endl;
    
    
    
    
    
    
            break;
        default:
            cout<<"Invalid input";
            system("PAUSE");
            break;
        }
    }
    
    char Map::returnLocation(int x, int y){
    cout<<x<<endl;
    cout<<y<<endl;
    char aSpot = _mapData[y][x];
    return aSpot;
    
    }
    
    #pragma once
    #include <vector>
    #include <fstream>
    #include <string>
    #include <tuple>
    #include <ctime>
    #include <random>
    #include "Player.h"
    #include "Monster.h"
    
    using namespace std;
    
    class Map
    
    {
    public:
        Map();      //Constructor
        void load(string levelName);
        void obtainSpawningLocations(char characterToken, Character &aCharacter);
        void checkMovementMonsters(char input, Monster &aMonster);
    
        //void obtainSpawningLocationsForMonsters(char characterToken, Monster aMonster);
    
        void print();
        void checkMovement(char input, Player &aPlayer);
        void movement(char characterToken);
        char returnLocation(int x,int y);
    
       // int numberOfSpawnPoints;
    
    private:
        vector <string> _mapData;
        Player _player;
        Monster _monster;
    
    
    };
    
    #include <iostream>
    #include <string>
    #include "Monster.h"
    
    using namespace std;
    
    Monster::Monster(){
    
    }
    void Monster::moveAround(){
    cout<<"Monster Mash"<<endl;
    }
    
    #pragma once
    #include <string>
    #include "Character.h"
    
    class Monster: public Character{
    
    public:
        Monster();
        virtual void moveAround();
    
    
    protected:
    
        char _token = 'M';
        int _x;
        int _y;
    };
    
    #include <iostream>
    #include <string>
    #include "Werewolf.h"
    
    using namespace std;
    
    Werewolf::Werewolf(){
    
    }
    
    void Werewolf::moveAround(){
        cout<<"Werewolf moving around"<<endl;
    }
    
    #pragma once
    #include <string>
    #include "Character.h"      //For inheritance/polymorphism
    #include "Monster.h"
    
    
    class Werewolf: public Monster{
    public:
        Werewolf();
        void moveAround();
    
    private:
    
        char _token = 'W';
    
    };
    
    #include <iostream>
    #include <string>
    #include "Vampire.h"
    
    using namespace std;
    
    Vampire::Vampire(){
    
    }
    
    void Vampire::moveAround(){
        cout<<"Vampire moving around"<<endl;
    }
    
    #pragma once
    #include <string>
    #include "Character.h"      //For inheritance/polymorphism
    #include "Monster.h"
    
    
    class Vampire: public Monster{
    public:
        Vampire();
        virtual void moveAround();
    
    private:
    
        char _token = 'V';
    
    };
    
    Player::Player(){
    
    }
    
    #pragma once
    #include <string>
    #include "Character.h"
    using namespace std;
    
    class Player : public Character {
    
    public:
        Player();  
    
    protected:
        int _x;
        int _y;
        char _token = '@';
    };
    
    #include <iostream>
    #include "GameSystem.h"
    using namespace std;
    
    int main()
    {
    GameSystem gameSystem("LevelOne.txt");
    gameSystem.startGame();
        return 0;
    }
    
    ############################################
    #..........................................#
    #..........................................#
    #...........................^..............#
    #..........................................#
    #......................#...................#
    #......................#...................#
    #......................#...................#
    #............^.........#...................#
    #......######..........#..&................#
    #......\...............#...................#
    #......................#...................#
    #..........................................#
    #..........................................#
    ############################################