jjzjj

c++ - 访问数组中的对象重新创建对象?

coder 2024-06-21 原文

我正在制作主机游戏和 map 。 map 是一个 vector 数组。 vector 包含我打印到控制台的字符。我的代码:

“窗口.h”

#include <string>
#include <vector>

class Row {
public:
    std::vector<char> row;
    int id;
    Row();
    void printRow();
    void resetRow();
    void insertStringIntoRow(std::string toInsert, int startIndex);
    std::vector<char> getRow() {
        return row;
    }
};

class Window {
public:
    void showMap();
    void writeToMap(std::string stringToInsert, int rowNum, int startIndex);
    void writeInRectangle(std::string stringToWrite, int rowNum, int startIndex);
    void setCursorToPosition(int x, int y);
    void resetMap();
    Row getRowAt(int index);
};

void initColors();
void setWindow(Window windowToSet);
Window getGameWindow();

“窗口.cpp”

#include "Window.h"
#include <iostream>
#include <Windows.h>
#include <WinBase.h>
#include <stdlib.h>
#include "color.h"

using namespace eku;

Row map[25];

//Class Window
void Window::showMap() {
    setCursorToPosition(0, 0);
    for (int i = 0; i < 25; i++) {
        getRowAt(i).printRow();
    }
}

void Window::writeToMap(std::string stringToInsert, int rowNum, int startIndex) {
    Row r = getRowAt(rowNum);
    r.insertStringIntoRow(stringToInsert, startIndex);
}

void Window::writeInRectangle(std::string stringToWrite, int rowNum, int startIndex) {
    if (startIndex != 0) {
        std::string topbar = "~";
        for (int i = 0; i < stringToWrite.length() + 2; i++) {
            topbar += ' ';
        }
        topbar += '^';
        getRowAt(rowNum - 1).insertStringIntoRow(topbar, startIndex - 1);
    }

    std::string toInsert = "~ ^" + stringToWrite + "~ ^";
    getRowAt(rowNum).insertStringIntoRow(toInsert, startIndex - 1);

    if (startIndex != 25) {
        std::string bottombar = "~";
        for (int i = 0; i < stringToWrite.length() + 2; i++) {
            bottombar += ' ';
        }
        bottombar += '^';
        getRowAt(rowNum + 1).insertStringIntoRow(bottombar, startIndex - 1);
    }
}

void Window::setCursorToPosition(int x, int y) {
    HANDLE hOut;
    COORD Position;
    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    Position.X = x;
    Position.Y = y;

    SetConsoleCursorPosition(hOut, Position);
}

void Window::resetMap() {
    for (Row row : map) {
        row.resetRow();
    }
}

Row Window::getRowAt(int index)
{
    return map[index];
}

//Class Row
const char WHITEBACKCOL = '~';
const char DEFCOL = '^';

int i = 0;

Row::Row() {
    row.resize(80, ' ');
    id = i;
    i++;
}

void Row::printRow() {
    for (int i = 0; i < row.size(); i++) {
        switch (row[i]) {
        case WHITEBACKCOL:
            setcolor(black, white);
        case DEFCOL:
            setcolor(white, black);
        default:
            std::cout << row[i];
        }
    }
}

void Row::resetRow() {
    row.resize(80);
    for (int i = 0; i < 80; i++) {
        row[i] = ' ';
    }
}

void Row::insertStringIntoRow(std::string toInsert, int startIndex) {
    int endIndex = (startIndex + toInsert.length());
    int stringPos = 0;
    for (int i = startIndex; i < endIndex; i++) {
        if (i < row.size() - 1) {
            row.at(i) = toInsert[stringPos];
        }
        else {
            row.push_back(toInsert[stringPos]);
        }
        stringPos++;
    }
}
Window defWindow;

void initColors() {
    concolinit();
    setcolor(white, black);
}

void setWindow(Window windowToSet) {
    defWindow = windowToSet;
}

Window getGameWindow() {
    return defWindow;
}

" main.cpp "

#include <iostream>
#include "GameEngine.h"
#include "Window.h"

int main() {
    setWindow(Window());
    initColors();

    getGameWindow().writeInRectangle("Hia", 1, 10);

    getGameWindow().showMap();
}

每当我调用 showMap() 时,我得到的只是一个空白的控制台。它似乎只打印默认的空间映射而不是我输入的文本。我还尝试仅使用 printRow() 来打印我编辑的单行,但它们也只显示空格。 我能够在 insertStringIntoRow() 方法中查看 vector 行的更改,但是即使更改应该在那里,它们也没有显示在其他任何地方。几乎每次我访问它时,我的 Row 对象都会被创建。我是 C++ 的新手,所以感谢您的帮助。提前致谢!

最佳答案

此功能使用不当。警告标志是它是非常量的,但用作访问器。它返回 vector 的拷贝,而不是引用。

std::vector<char> getRow() {
    return row;
}

您调用它的方式,您希望它就地修改该行,但您实际上所做的只是修改该行的拷贝,然后立即将其丢弃。示例:

getRowAt(rowNum).insertStringIntoRow(toInsert, startIndex - 1);

解决此问题的简单方法是从 getRow() 返回一个引用:

std::vector<char> & getRow() {
    return row;
}

另一件需要修复的事情是将它分配给一个临时变量,而不是直接使用它。在这种情况下,您可以将临时文件设为引用:

Row & r = getRowAt(rowNum);
r.insertStringIntoRow(stringToInsert, startIndex);

实现它的正确方法是提供一个常量版本,这样它仍然可以在调用者不想修改的常量对象上调用

const std::vector<char> & getRow() const {
    return row;
}

我只把这个额外的部分放在这里是因为这是一个很好的做法,但你不应该在这个程序中这样做。它会使你的代码变得困惑,因为它已经充满了更糟糕的做法 =)

关于c++ - 访问数组中的对象重新创建对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31130590/

有关c++ - 访问数组中的对象重新创建对象?的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  3. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  4. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  5. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  6. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  7. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  8. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  9. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  10. ruby - 多次弹出/移动 ruby​​ 数组 - 2

    我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby​​数组,我们在StackOverflow上找到一

随机推荐