修改类c ++上的引用成员

时间:2015-03-05 04:36:40

标签: c++ class pointers smart-pointers members

我是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,没有?

问候和感谢。

3 个答案:

答案 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;
    }