【问题标题】:Problem with std::vector and/or polymorphismstd::vector 和/或多态性问题
【发布时间】:2019-01-22 11:02:51
【问题描述】:

我到处寻找答案,但找不到答案。以下是我在 Visual Studio 2017 中的小程序。 它不会打印我添加的任何一个“房间”——它会发布随机值。 代码编译完美。只是输出是错误的。 我认为大多数代码都无关紧要,老实说,我不知道我做错了什么。我认为它可能在向量/继承部分。

编辑:很快就解决了。我插入了一个局部变量的指针指向我的向量。谢谢。

房间.h:

#pragma once
#include <vector>

class Room {
protected:
    int i;
    int j;
    int size;
    char** objs;

public:
    Room(int _i = 0, int _j = 0, int _size = 0);
    int get_i() const { return i; }
    int get_j() const { return j; }
    int get_size() const { return size; }
    char** get_objs() const { return objs; }
    virtual void make_room() = 0;
};

class Maze : public Room {
public:
    Maze(int _i, int _j, int _size);
    void make_room();
};

class Board {
    std::vector<Room*> rooms;

public:
    Board() {}
    void add_room(int i, int j, int v);
    void print_a_room() const;
};

Room.cpp:

#include "room.h"
#include <iostream>

Room::Room(int _i, int _j, int _size) : i(_i), j(_j), size(_size) {
    objs = new char*[_size];
    for (int i = 0; i < _size; i++) {
        objs[i] = new char[_size];
        for (int j = 0; j < _size; j++) {
            objs[i][j] = ' ';
        }
    }
}

Maze::Maze(int _i, int _j, int _size) : Room(_i, _j, _size) {
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            objs[i][j] = '*';
        }
    }
    make_room();
}

void Maze::make_room() {
    int x = 1;
}

void Board::add_room(int i, int j, int v) {
    rooms.push_back(&Maze(i, j, v));
}

void Board::print_a_room() const {
    Room* r = rooms.back();
    std::cout << r->get_i() << "," << r->get_j() << std::endl;
}

main.cpp:

#include "room.h"
#include <iostream>

int main() {
    Board b;
    b.add_room(1, 2, 10);
    std::cout << "hello" << std::endl;
    b.add_room(3, 4, 5);
    b.print_a_room();
    return 0;
}

我们将不胜感激。

【问题讨论】:

  • rooms.push_back(&amp;Maze(i, j, v)); 看起来很可疑。
  • 你是对的。它是一个局部变量。我什至没有考虑过....愚蠢的错误。谢谢。
  • @Itai 不要编辑问题并说您已经解决了问题,而是接受以下为您提供解决方案的答案之一。
  • 我建议提高编译器的警告级别。
  • 我会寻找有关提高警告级别的指南,是的。谢谢。

标签: c++ visual-studio-2017


【解决方案1】:

这不应该首先编译 (here's why),但是因为您的编译器显然允许它...

您正在存储临时对象的地址:

void Board::add_room(int i, int j, int v) {
    rooms.push_back(&Maze(i, j, v));   // <---- There
}

在此表达式中创建的 Maze 对象在表达式结束后立即死亡,并且您会留下悬空指针,特别是没有指向任何地方。

除非您想要多态行为,否则通常不需要将指针存储在向量中。在这种情况下,请使用合适的智能指针,例如 shared_ptrunique_ptr

【讨论】:

  • 可以存储指向房间的指针。只需将指针传递给动态分配的对象(通过new)。如果向量将按值存储房间,object slicing 将会发生。
  • @Zak 对,还没有考虑过他们的班级结构。将编辑。
  • 谢谢!由于某种原因,我忘记了整个局部变量范围的事情。从现在开始会努力记住。
  • @rustyx 因为它正在获取右值的地址。
【解决方案2】:

问题是这样的:rooms.push_back(&amp;Maze(i, j, v))

问题是当前对象是在栈上分配的,在这一行之后,这个对象就会被销毁。

Room* 更改为 Room 不是解决方案 - 如果这样做,您将无法拥有多态性。

最佳解决方案: rooms.push_back(new Maze(i, j, v)).

注意: 您需要定义三法则,因为存在共享内存。 当你执行pop_back 时,首先在房间的当前元素上调用运算符delete,然后调用std::vectorpop_back 方法。

【讨论】:

  • 谢谢!我确实需要记住在弹出它之前将其删除。我会把它改成新的。
  • 是的,我读了很多。智能指针会成功,所以我不需要手动删除东西吗? (除非我分配了一个二维数组)
猜你喜欢
  • 1970-01-01
  • 2011-01-19
  • 2023-03-21
  • 2015-04-08
  • 2011-06-29
  • 1970-01-01
  • 2018-05-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多