自定义类构造函数中的 C++ 指针赋值

标签 c++ class pointers vector

所以我有一个自定义类“Book”,它有一堆成员变量,其中有另一个自定义类“Review”的 vector 和一个指向该 vector 的指针,因为我需要通过函数传递它调用驱动程序。驱动程序从文本文件中读取每本书的详细信息(如标题、作者、出版日期等),并将其插入到一个临时“书籍”对象中,然后将其添加到由驱动程序维护的 Books vector 中。这是从文件中读取的代码:

ifstream file("books.txt");
string line;
if(file.is_open())
{
    while(!file.eof())
    {
        Book buffBook;
        getline(file, line);
        buffBook.setTitle(line);
        getline(file, line);
        buffBook.setAuthor(line);
        getline(file, line);
        buffBook.setPubDate(line);
        getline(file, line);
        buffBook.setIsbn(line);
        getline(file, line);
        buffBook.setCategory(line);
        getline(file, line);
        buffBook.setFormat(line);
        getline(file, line);
        buffBook.setSynopsis(line);
        vectBooks.push_back(buffBook);
    }
}

else
    cout<<"File not found(1)!"<<endl;

file.close();

这是在 int main() 函数中运行的。
驱动程序的功能之一是添加评论,它从用户那里获取数据并将其插入到临时的“评论”对象中。然后将该对象传递给插入到相应书籍的评论 vector 中。以下是 addReview() 函数的代码:

void addReview()
{
    string name = "";
    string title;
    Book rTemp;
    cin.ignore();
    cout<<"Which book would you like to rate (Title)?: ";
    getline(cin, name);
    name = toLow(name);
    Review r;
    string re, user;
    int ra;
    cout<<"Username (Full Name): ";
    getline(cin, user);
    string fname = user.substr(0, user.find_first_of(' '));
    string lname = user.substr( user.find_first_of(' ') + 1, user.size());
    r.setUsrFName(fname);
    r.setUsrLName(lname);
    cout<<"Enter rating (1-5):";
    cin>>ra;
    r.setRating(ra);
    cout<<"Enter a short textual review: ";
    cin.ignore();
    getline(cin, re);
    r.setReview(re);
    for(unsigned int i = 0; i < vectBooks.size(); i++)
    {
         title = toLow(vectBooks[i].getTitle());
         if(title.find(name) != string::npos)
         {
             vectBooks[i].getReviews()->push_back(r);
         }
    }
}

现在的问题是,如果我添加评论,它会为所有书籍添加评论。换句话说,当我获取任何书籍的书籍信息时,评论会显示在所有书籍上。我认为这是指针的问题,因为似乎所有评论都存储在同一个 vector 中。我不确定我在哪里搞砸了,但我有一种感觉,指针在某个地方。任何帮助表示赞赏。

谢谢

更新

这个问题的标题是我在 Book 类的构造函数中将指针赋值给 Reviews vector ,这两个是成员变量。构造函数代码如下:

Book::Book()
{
    pointRev = &vectReviews;
}

更新 2

这是 Book 类和支持类的代码:

书.h

#ifndef BOOK_H_
#define BOOK_H_

#include <string>
#include <iostream>
#include <vector>
#include "review.h"

using namespace std;

class Book
{
private:
    string title;
    string author;
    string pubDate;
    string isbn;
    string category;
    string format;
    string synopsis;
    vector<Review> vectReviews;
    vector<Review>* pointRev;
public:
    Book::Book() : pointRev(&vectReviews) {};
    string getAuthor() const;
    string getCategory() const;
    string getFormat() const;
    string getIsbn() const;
    string getPubDate() const;
    string getSynopsis() const;
    string getTitle() const;
    vector<Review>* getReviews();
    void setAuthor(string author);
    void setCategory(string category);
    void setFormat(string format);
    void setIsbn(string isbn);
    void setPubDate(string pubDate);
    void setSynopsis(string synopsis);
    void setTitle(string title);

    friend ostream& operator <<(ostream& out, Book& book);
    vector<Review> *getPointRev() const;
    vector<Review> getVectReviews() const;
    void setPointRev(vector<Review> *pointRev);
    void setVectReviews(vector<Review> vectReviews);


};

#endif /* BOOK_H_ */

书。 cpp

#include "book.h"
string Book::getAuthor() const
{
    return author;
}

string Book::getCategory() const
{
    return category;
}

string Book::getFormat() const
{
    return format;
}

string Book::getIsbn() const
{
    return isbn;
}

string Book::getPubDate() const
{
    return pubDate;
}

string Book::getSynopsis() const
{
    return synopsis;
}

string Book::getTitle() const
{
    return title;
}

void Book::setAuthor(string author)
{
    this->author = author;
}

void Book::setCategory(string category)
{
    this->category = category;
}

void Book::setFormat(string format)
{
    this->format = format;
}

void Book::setIsbn(string isbn)
{
    this->isbn = isbn;
}

void Book::setPubDate(string pubDate)
{
    this->pubDate = pubDate;
}

void Book::setSynopsis(string synopsis)
{
    this->synopsis = synopsis;
}

void Book::setTitle(string title)
{
    this->title = title;
}

vector<Review> *Book::getPointRev() const
{
    return pointRev;
}

vector<Review> Book::getVectReviews() const
{
    return vectReviews;
}

void Book::setPointRev(vector<Review> *pointRev)
{
    this->pointRev = pointRev;
}

void Book::setVectReviews(vector<Review> vectReviews)
{
    this->vectReviews = vectReviews;
}

vector<Review>* Book::getReviews()
{
    return pointRev;
}


ostream& operator <<(ostream& out, Book& book)
{
    out<<"\nTitle: "<<book.getTitle()<<endl;
    out<<"Author: "<<book.getAuthor()<<endl;
    out<<"Publish Date: "<<book.getPubDate()<<endl;
    out<<"ISBN: "<<book.getIsbn()<<endl;
    out<<"Category: "<<book.getCategory()<<endl;
    out<<"Format: "<<book.getFormat()<<endl;
    out<<"Synopsis: "<<book.getSynopsis()<<endl;
    cout<<"\n--- Reviews ---"<<endl;
//  vector<Review>* revs = book.getReviews();
    for(unsigned int h = 0; h < book.getReviews()->size(); h++)
    {
        cout<<"Review by: "<<book.getReviews()->at(h).getUsrFName()<<" "<<book.getReviews()->at(h).getUsrLName()<<endl;
        cout<<"Rating: "<<book.getReviews()->at(h).getRating()<<endl;
        cout<<"Review: "<<book.getReviews()->at(h).getReview()<<endl;
    }

    return out;
}

review.h

#ifndef REVIEW_H_
#define REVIEW_H_

#include <string>

using namespace std;

class Review
{
private:
    int rating;
    string review;
    string usrFName;
    string usrLName;
public:
    int getRating() const;
    string getReview() const;
    void setRating(int rating);
    void setReview(string review);
    string getUsrFName() const;
    string getUsrLName() const;
    void setUsrFName(string usrFName);
    void setUsrLName(string usrLName);
};

#endif /* REVIEW_H_ */

评论.cpp

#include "review.h"



int Review::getRating() const
{
    return rating;
}

string Review::getReview() const
{
    return review;
}


void Review::setRating(int rating)
{
    this->rating = rating;
}

string Review::getUsrFName() const
{
    return usrFName;
}

string Review::getUsrLName() const
{
    return usrLName;
}

void Review::setUsrFName(string usrFName)
{
    this->usrFName = usrFName;
}

void Review::setUsrLName(string usrLName)
{
    this->usrLName = usrLName;
}

void Review::setReview(string review)
{
    this->review = review;
}

最佳答案

从您描述的行为来看,复制构造函数正在运行并生成指向同一 vector 的两个对象。 push_back 确实使用了复制构造函数。

但您的第一个代码片段不会复制同一本 Book,而是在每次循环迭代时创建一个新的 Book(然后复制到vectBooks.

如果 Book 没有正确的用户定义的复制构造函数,那么您就没有正确管理 pointRev。从观察到的行为来看,我相信您有一个释放 pointRev 的析构函数,然后 vectBooks 中的拷贝留下一个悬空指针。根据标准,这之后的一切都属于未定义行为的范畴,意思是“任何事情都可能发生”然后下一本Book恰好重用了相同的内存区域,所以所有的Book 的实例最终在野指针中具有相同的值。然后更新任何一个都会改变所有 Book 实例看到的 vector (它甚至不再存在)。

你为什么要使用指向 std::vector 的指针?将 vector 作为直接数据成员放入类中要好得多,这样编译器就可以自动构造、复制和销毁它,而无需您的额外帮助。


当然,您完全有可能将 vectReviews 设置为全局变量,然后每本书都指向同一个实例。这样一来评论会同时出现在所有书籍中,因为它们共享您要添加评论的 vector 。

关于自定义类构造函数中的 C++ 指针赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5163833/

相关文章:

c++ - 编译此开源应用程序时出现问题

c++ - 如何在 `non-const reference of type char* &` 参数中硬编码 C 字符串

c++ - 将模板类的对象传递给另一个类的构造函数

java - 引用匿名类?

java - 当我在运行时只能在字符串变量中找到类的名称时,如何使用该类?

c - 显示函数指针代码中的错误

将 unsigned int 转换为 int 指针 段错误

c++ - NaN 或 false 作为 double 返回值

c++ - 将二维数组作为参数传递给采用一维数组的函数

c++ - 在匿名命名空间中定义 QObject 派生类?