Я использую производный класс и вектор указателей на объекты из указанного класса. У меня возникли проблемы с выполнением конструкторов копирования и т. Д., Даже после многого прочтения. Я использую C++ 11.Вектор указателей объектов и объектов, выходящих из области видимости
У меня есть петля, где создаются новые объекты производного класса, и тогда я хочу поместить их в вектор. Но поскольку это вектор указателей, я должен вместо этого указать адрес созданного объекта.
Я считаю, что мои проблемы проистекают из этого факта вместе с объектами, выходящими из области видимости и т. Д., И я не могу реализовать конструкторы копирования/конструкторы назначения копирования и т. Д. Удовлетворительным образом.
Я сделал минимальный пример, который, на мой взгляд, иллюстрирует мою проблему. Скажем, начальная настройка выглядит следующим образом (я знаю, что это не имеет особого смысла, например, с указателем *n
, но я думаю, что это показывает проблемы с моим фактическим кодом):
using namespace std;
#include <iostream>
#include <vector>
class Base {
protected:
int* n;
public:
void display(string name="") {cout << name << "n = " << *n << endl;}
Base() {}
Base(int n_) {
*n=n_;
cout << "Initialised to " << *n << endl;
}
};
class Derived : public Base {
public:
Derived() : Base() {}
Derived(int n_) : Base(n_) {}
};
int main(int argc, const char* argv[]) {
vector<Base*> list;
for(int i=0;i<5;i++) {
Derived tmp(i);
tmp.display("Tmp: ");
list.push_back(&tmp);
}
cout << endl;
for(int i=0;i<list.size();i++) {
cout << "Address of " << i << ": " << list[i] << endl;
list[i]->display("Element "+to_string(i)+" : ");
}
}
Выход этого является :
Initialised to 0
Tmp: n = 0
Initialised to 1
Tmp: n = 1
Initialised to 2
Tmp: n = 2
Initialised to 3
Tmp: n = 3
Initialised to 4
Tmp: n = 4
Address of 0: 0x7fff3a1df2d0
Element 0 : n = 0
Address of 1: 0x7fff3a1df2d0
Element 1 : n = 0
Address of 2: 0x7fff3a1df2d0
Element 2 : n = 0
Address of 3: 0x7fff3a1df2d0
Element 3 : n = 0
Address of 4: 0x7fff3a1df2d0
Element 4 : n = 0
Таким образом, после цикла все элементы в списке точки к тому же адресу, где п = 0 (вероятно, неопределенное поведение от tmp
из области видимости).
Так, а не просто положить адрес tmp
в list
Я думаю, что я каким-то образом придется создавать экземпляры Derived
, которые выживают петлю, пока еще только имея адреса в list
.
Как уже упоминалось, я пытался сделать это, используя различные специальные функции-члены без везения.
Обратите внимание, что может показаться, что реализация вектора самих объектов может быть проще, но это приводит к другим проблемам в моем фактическом коде. Если я не смогу получить эту работу, я попробую это вместо этого.
Выделение неинициализированного указателя является неопределенным поведением: вам нужно выделить некоторую память для 'n', чтобы указать, прежде чем вы будете делать * * n = n_' в конструкторе' B'. Для 'list.push_back (&tmp);' вы на самом деле выделили (автоматическую) память, но, как вы можете видеть по значению указателей, память всегда одна и та же: она используется повторно, поскольку область действия 'tmp' переходит только в конец цикла. – BeyelerStudios
Какова цель 'Base :: n'? Почему это указатель? –
@BeyelerStudios: Вы имеете в виду, например, добавление' n = 0' перед '* n = n_'? @Joachim Pileborg: Как упоминалось в OP, я знаю, что это не имеет смысла, это очень простая примерная версия большой программы – jorgen