Вектор указателей на объекты, кажется, не работает так, как задумано в C ++ - PullRequest
2 голосов
/ 10 марта 2011

Я был последователем в течение долгого времени, но я впервые задаю вопрос.В двух словах, проблема в том,vector<Student*> studentvector, который является вектором указателей объектов, похоже, возвращает информацию об ученике как student;но когда я печатаю, чтобы увидеть первый в векторе, работает ли он должным образом, я вижу, что он всегда обновляет первую запись новой поступающей информацией об ученике, хотя при * 1003 проблем не возникает.сколько раз я звоню addStudent(...) но он заполняет весь вектор информацией последнего студента.Что можно сделать, чтобы преуспеть в заполнении вектора правильной информацией в этом кадре, без использования умных указателей или продвинутых вещей?

Извините, если я неясен в своем вопросе.Вы можете привести меня, чтобы предоставить то, что также необходимо, чтобы понять проблему.Заранее спасибо.

addStudent(const string alias, const string name) throw(StudentException)
{
Student* student = new Student(alias, name)
studentvector.push_back(student);
cout << studentvector.front() << endl;
}

Это реализация Student;

#include "Student.h"

string *Alias;
string *Name;


Student::Student(string alias)
{
    Alias = new string(alias);
}

Student::Student(string alias, string name)
{
    Alias = new string(alias);
    Name = new string(name);
}

Student::~Student()
{
    delete Alias;
    delete Name;
}

const string& Student::getAlias() const
{
    return *Alias;
}

void Student::setAlias(const string& alias)
{
    *Alias = alias;
}

const string& Student::getName() const
{
    return *Name;
}

void Student::setName(const string& name)
{
    *Name = name;
}

Считать, что псевдоним не зарезервирован.

Ответы [ 6 ]

4 голосов
/ 10 марта 2011

Doh!Вот ваша проблема - все объекты типа Student используют одни и те же глобальные указатели:

<code>string *Alias;
string *Name;

Сделайте их двумя членами вашего класса


class Student
{
private:
    string *Alias;
    string *Name;
//..
}; 

РЕДАКТИРОВАТЬ : Кроме того, я не думаю, что это хорошая идея использовать указатель на std::string, я бы посоветовал вам использовать так:

class Student
{
private:
    string Alias;
    string Name;
//..
}; 
</code>
1 голос
/ 10 марта 2011

Ваш Student.cpp определяет один глобальный указатель Alias и один указатель Name. То, что вы действительно хотите, это отдельные Alias и Name для каждого Student объекта. Вы делаете это, добавляя членов в класс:

class Student {
public:
  Student(const std::string& a, const std::string& n);
  //...
private:
  std::string Alias;
  std::string Name;
};

Student::Student(const std::string& a, const std::string& n)
  : Alias(a), Name(n)
{}
1 голос
/ 10 марта 2011

Я могу быть здесь в бреду, но разве вы не специально печатаете спереди, одновременно отталкивая?

studentvector.push_back(student);
cout << studentvector.front() << endl;

Вы нажимаете на заднюю часть, а не на переднюю, а затем распечатываете то, что находится впереди. Конечно, вы не видите изменение фронта. Вам нужно распечатать назад или толкнуть вперед. Если push front не доступен, вы можете использовать insert(container.begin(), object).

Вам также необходимо переместить эти глобальные строковые переменные в класс как члены, чтобы для каждого экземпляра Student у студента были экземпляры Name и Alias.

Еще одно замечание ... вы динамически распределяете строковый класс. Назначение класса string - обработать для вас динамическую память строки char*. Насколько я могу судить из вашего кода, у вас нет причин использовать string* s в этой ситуации. string будет обрабатывать new и delete внутри вас.

1 голос
/ 10 марта 2011

Я согласен с тем, что сказали все остальные.Однако я не могу воспроизвести проблему, о которой вы говорите.В частности, следующий (довольно странный) код правильно выводит две строки с надписью «Student (foo, bar)».

#include <iostream>
#include <vector>
#include <string>

// NOTE WELL: many things in this code are bad style and should not be imitated.
// One of them is the namespace-polluting using-directive below:
using namespace std;

struct Student {
  string alias, name;
  Student(string a, string n) : alias(a), name(n) {}
};
class StudentException : public exception {};

vector<Student*> studentvector;

ostream& operator<<(ostream& stream, Student* student) {
  stream << "Student(" << student->alias << "," << student->name << ")";
  return stream;
}

void addStudent(const string alias, const string name) throw(StudentException)
{
  Student* student = new Student(alias, name);
  studentvector.push_back(student);
  cout << studentvector.front() << endl;
}

int main(void) {
  addStudent("foo","bar");
  addStudent("baz","quux");
}

Может быть полезно узнать, как ваш (неработающий) код отличается отвыше.

Пара замечаний, которые, возможно, могут иметь отношение:

  1. Вы случайно не путаете передний и задний концы вектора?
  2. Если (в отличие от вашей функции addStudent) ваш реальный код имеет одиночный объект Student и изменяет его, а затем помещает указатель на него на ваш вектор, тогда, конечно, вы получите неправильные результатыВы описываете, потому что это будет один и тот же указатель каждый раз.
0 голосов
/ 10 марта 2011

Если у вас есть Boost, посмотрите Контейнеры указателей повышения .

0 голосов
/ 10 марта 2011

std :: vector :: front () вернет вам ссылку на первый элемент вектора.Если вы хотите удалить элемент, вам нужно вызвать pop_back (), который вернет элемент и удалит его из вектора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...