我是c ++的新手,我来自Java。所以我猜测通过引用变量修改类成员。
在java中添加元素到现有列表(类成员)只需要使用“添加”方法,这就是全部,但在这里我不明白为什么我不能用我的get修改向量方法
class Student {
public:
Student(std::string n):name(n){};
std::string getName(){return name;};
void setName(std::string name){this->name = name;};
private:
std::string name;
};
class Subject {
public:
std::vector<Student> getStudents(){return students;};
void setStudents(std::vector<Student> students){this->students = students;};
private:
std::vector<Student> students;
};
int main() {
// Students
Student s1("Abi");
Student s2("Nat");
Student s3("Osi");
// normal case
Subject math;
std::vector<Student> students;
students.push_back(s1);
math.setStudents(students);
math.getStudents().push_back(s2);
// print names
for(unsigned int i=0; i < math.getStudents().size();i++) {
std::cout << math.getStudents()[i].getName() << std::endl;
}
// pointers
std::cout << "Ptr------------------" << std::endl;
Subject *mathPtr;
mathPtr = &math;
// try to add student to the existing vector
mathPtr->getStudents().push_back(s2); // it doesnt work
// it works if i add a new vector
std::vector<Student> studentsPtr;
studentsPtr = mathPtr->getStudents();
studentsPtr.push_back(s2);
mathPtr->setStudents(studentsPtr);
// print students of original object
for(unsigned int i=0; i < math.getStudents().size();i++) {
std::cout << math.getStudents()[i].getName() << std::endl;
}
// pointers
std::cout << "Smart_ptr-------------" << std::endl;
std::shared_ptr<Subject> mathSmartPtr;
mathSmartPtr = std::make_shared<Subject>(math);
// try to add student to the existing vector
mathSmartPtr->getStudents().push_back(s3); //it doesnt work
std::vector<Student> studentsSmartPtr;
studentsSmartPtr = mathPtr->getStudents();
studentsSmartPtr.push_back(s3);
mathSmartPtr->setStudents(studentsSmartPtr);// it doesnt work too
// print students of original object
for(unsigned int i=0; i < math.getStudents().size();i++) {
std::cout << math.getStudents()[i].getName() << std::endl;
}
}
我不明白为什么智能指针不起作用。它假设是一个普通的指针+ autodelete,没有?
问候和感谢。
答案 0 :(得分:1)
你的代码中的问题是你正在制作很多学生载体的副本,却没有意识到。来自Java的常见问题。
具体来说,在你的Subject类中,方法getStudents没有做你认为它做的事情:
std::vector<Student> getStudents(){return students;};
它制作了一个名为“学生”的矢量副本,并将副本返回给您,而不是原始副本。您的代码中的其他地方也会发生同样的情况,但可能会产生较少的有害影响。
您可以通过包含引用运算符来轻松解决此问题:
std::vector<Student>& getStudents(){return students;};
将像在Java中一样工作。但是存在一个危险:如果您的Subject对象被销毁,那么该向量将与它一起使用 - 即使您在其他地方存储了对它的引用。例如,这可能会导致程序崩溃:
Subject* mathPtr = new Subject;
// try to add student to the existing vector
std::vector<Student>& s = mathPtr->getStudents();
delete mathPtr;
s.push_back(s2); // accesses already-freed memory
答案 1 :(得分:1)
您已声明getStudents
返回students
向量的副本。
std::vector<Student> getStudents(){return students;};
所以当你这样做时:
getStudents().push_back(...)
它只会添加到矢量的副本,它会立即被销毁,因为您没有将其存储在任何地方。因此,原始students
向量不会被修改。
如果您想要push_back
原始矢量,则需要向其返回 参考 :
std::vector<Student>& getStudents(){return students;};
^
答案 2 :(得分:-1)
这可能会有所帮助
class Student {
public:
Student(std::string n) :name(n){};
std::string getName(){ return name; };
void setName(std::string name){ this->name = name; };
private:
std::string name;
};
class Subject {
public:
Student * getStudent(std::string name);
void setStudents(Student* student);
void PrintStudents();
private:
std::vector<Student*> students;
typedef std::vector<Student*>::iterator iter;
};
Student* Subject::getStudent(std::string name)
{
Student* stud = NULL;
for (iter i = students.begin(); i != students.end(); ++i)
{
if ((*i)->getName() == name)
stud = (*i);
}
return stud;
}
void Subject::setStudents(Student* student)
{
students.push_back(student);
}
void Subject::PrintStudents()
{
for (iter i = students.begin(); i != students.end(); ++i)
{
std::cout << (*i)->getName() << std::endl;
}
}
int main()
{
Student* s1;
s1 = new Student("Kavinda");
Student s2("Liza");
Subject math;
math.setStudents(s1);
math.setStudents(&s2);
Student *s3 = math.getStudent("Kavinda");
if (s3)
std::cout << s3->getName() << std::endl;
else
std::cout << "No Student Exists having that name\n" << std::endl;
math.PrintStudents();
getchar();
return 0;
}