使用指针更改代码以实现多对多关系
Change the Code Using Pointers to Achieve Many-to-Many Relationship
我在Movie.hpp
中有以下代码
#ifndef MOVIE_H
#define MOVIE_H
class Movie
{
private:
std::string title;
public:
std::string getTitle() const {return this->title;} // const added
void setTitle(std::string newTitle){this->title = newTitle;}
};
#endif
在Actor.hpp
#ifndef ACTOR_H
#define ACTOR_H
#include "Person.hpp"
#include "Movie.hpp"
class Actor: public Person
{
private:
std::vector<Movie> movieList;
public:
void addMovie(Movie newMovie){this->movieList.push_back(newMovie);}
void printMovies()
{
for(Movie movie: this->movieList)
{
std::cout << movie.getTitle() << '\n';
}
}
};
#endif
在主可执行文件中Main.cpp
Movie movie1, movie2, movie3;
Comment comment1, comment2, comment3;
Viewer viewer1, viewer2;
Actor actor1, actor2;
Celebrity celebrity1;
movie1.setTitle("Transformers");
movie2.setTitle("Interstellar");
movie3.setTitle("The Matrix");
actor1.setName("Brad");
actor1.setAge(57);
actor1.addMovie(movie1); //here
actor1.addMovie(movie2);
actor2.setName("Justin");
actor2.setAge(30);
actor2.addMovie(movie1); // added
actor2.addMovie(movie3);
现在,我被告知我的代码没有遵循多对多关系。换句话说,如果 actor1 和 actor2 与同一部电影有联系,他们应该共享同一个 'Movie' 对象。在我的例子中,他们有不同的电影对象。
正确的方法是在 Actor 中存储指向 Movie 的指针:
std::vector<Movie*> movieList;
(指针的集合,不是对象的集合)
和电影里面:
std::vector<Actor*> actorList;
另一个正确的方法,我更喜欢这个,是添加一个单独的 class
class Role {
private:
Actor* actor;
Movie* movie;
};
并在 Movie 和 Actor 中存储此类对象的集合,这里的值(不是指针)是可以的
std::vector<Role> movieList; //inside Actor
std::vector<Role> actorList; //inside Movie
所以,实际问题是我无法实施上述解决方案。如果我按照上面的说明添加指针或 Role 对象,有人可以告诉我将在以前的代码中进行的更改吗?
如果 Movie
对象需要在 Actors
之间共享,另一种方法是使用 std::vector<std::shared_ptr<Movie>>
而不是 std::vector<Movie>
或 std::vector<Movie*>
.
std::vector<Movie>
之所以困难的原因基本上就是您所发现的。 Movie
对象与另一个 Movie
对象分开,即使 Movie
具有相同的名称。
那么 std::vector<Movie*>
会出现问题的原因是,是的,您现在可以“共享”Movie
对象,但是维护跟踪共享的数量 Movie
对象变得笨重。
std::vector<std::shared<Movie>>
进来帮忙。 std::shared_ptr 不仅仅是一个指针,而是一个智能指针,这意味着它将是一个引用计数指针,当所有对该对象的引用超出范围时,它将自行销毁。因此没有内存泄漏,这与您使用原始 Movie*
并以某种方式管理不善不同。
#ifndef ACTOR_H
#define ACTOR_H
#include "Person.hpp"
#include "Movie.hpp"
#include <memory>
class Actor: public Person
{
private:
std::vector<std::shared_ptr<Movie>> movieList;
public:
void addMovie(std::shared_ptr<Movie> newMovie) {this->movieList.push_back(newMovie);}
void printMovies()
{
for(auto& movie: this->movieList)
{
std::cout << movie->getTitle() << '\n';
}
}
};
#endif
然后将 类 的最小化版本和测试 main
函数放在一起:
#include <memory>
#include <vector>
#include <string>
#include <iostream>
class Movie
{
private:
std::string title;
std::string m_rating = "G";
public:
std::string getTitle() const {return this->title;} // const added
void setTitle(std::string newTitle){this->title = newTitle;}
void setRating(std::string rating) { m_rating = rating; }
std::string getRating() const { return m_rating; }
};
class Person {};
class Actor: public Person
{
private:
std::vector<std::shared_ptr<Movie>> movieList;
public:
void addMovie(std::shared_ptr<Movie> newMovie) {this->movieList.push_back(newMovie);}
void printMovies()
{
for(auto& movie: movieList)
{
std::cout << movie->getTitle() << " Rating: " << movie->getRating() << '\n';
}
}
};
int main()
{
// Create our movies
auto movie1 = std::make_shared<Movie>();
auto movie2 = std::make_shared<Movie>();
auto movie3 = std::make_shared<Movie>();
Actor actor1, actor2;
movie1->setTitle("Transformers");
movie2->setTitle("Interstellar");
movie3->setTitle("The Matrix");
actor1.addMovie(movie1);
actor1.addMovie(movie2);
actor2.addMovie(movie1);
actor2.addMovie(movie3);
std::cout << "actor 1 movies:\n";
actor1.printMovies();
std::cout << "\nactor 2 movies:\n";
actor2.printMovies();
// Set the rating to movie1 to "R"
movie1->setRating("R");
std::cout << "\n\nactor 1 movies:\n";
actor1.printMovies();
std::cout << "\nactor 2 movies:\n";
actor2.printMovies();
}
输出:
actor 1 movies:
Transformers Rating: G
Interstellar Rating: G
actor 2 movies:
Transformers Rating: G
The Matrix Rating: G
actor 1 movies:
Transformers Rating: R
Interstellar Rating: G
actor 2 movies:
Transformers Rating: R
The Matrix Rating: G
现在 actor1
和 actor2
实际上共享同一个 Movie
,称为“变形金刚”——它们不再是独立的对象。我添加了 setRating
和 getRating
函数来演示更改 movie1
的评级会将 actor1
和 actor2
的评级更改为 R
。
现在,没有什么能阻止您制作另一部同名电影(例如,movie4
名为“变形金刚”的电影)。如果这是一个问题,您将需要一个额外的数据结构来跟踪已经使用的名称(可能是 std::unordered_set<std::string>
)。但这是一个侧面点,只是为了让你知道这可能会发生。
我在Movie.hpp
中有以下代码#ifndef MOVIE_H
#define MOVIE_H
class Movie
{
private:
std::string title;
public:
std::string getTitle() const {return this->title;} // const added
void setTitle(std::string newTitle){this->title = newTitle;}
};
#endif
在Actor.hpp
#ifndef ACTOR_H
#define ACTOR_H
#include "Person.hpp"
#include "Movie.hpp"
class Actor: public Person
{
private:
std::vector<Movie> movieList;
public:
void addMovie(Movie newMovie){this->movieList.push_back(newMovie);}
void printMovies()
{
for(Movie movie: this->movieList)
{
std::cout << movie.getTitle() << '\n';
}
}
};
#endif
在主可执行文件中Main.cpp
Movie movie1, movie2, movie3;
Comment comment1, comment2, comment3;
Viewer viewer1, viewer2;
Actor actor1, actor2;
Celebrity celebrity1;
movie1.setTitle("Transformers");
movie2.setTitle("Interstellar");
movie3.setTitle("The Matrix");
actor1.setName("Brad");
actor1.setAge(57);
actor1.addMovie(movie1); //here
actor1.addMovie(movie2);
actor2.setName("Justin");
actor2.setAge(30);
actor2.addMovie(movie1); // added
actor2.addMovie(movie3);
现在,我被告知我的代码没有遵循多对多关系。换句话说,如果 actor1 和 actor2 与同一部电影有联系,他们应该共享同一个 'Movie' 对象。在我的例子中,他们有不同的电影对象。 正确的方法是在 Actor 中存储指向 Movie 的指针:
std::vector<Movie*> movieList;
(指针的集合,不是对象的集合)
和电影里面:
std::vector<Actor*> actorList;
另一个正确的方法,我更喜欢这个,是添加一个单独的 class
class Role {
private:
Actor* actor;
Movie* movie;
};
并在 Movie 和 Actor 中存储此类对象的集合,这里的值(不是指针)是可以的
std::vector<Role> movieList; //inside Actor
std::vector<Role> actorList; //inside Movie
所以,实际问题是我无法实施上述解决方案。如果我按照上面的说明添加指针或 Role 对象,有人可以告诉我将在以前的代码中进行的更改吗?
如果 Movie
对象需要在 Actors
之间共享,另一种方法是使用 std::vector<std::shared_ptr<Movie>>
而不是 std::vector<Movie>
或 std::vector<Movie*>
.
std::vector<Movie>
之所以困难的原因基本上就是您所发现的。 Movie
对象与另一个 Movie
对象分开,即使 Movie
具有相同的名称。
那么 std::vector<Movie*>
会出现问题的原因是,是的,您现在可以“共享”Movie
对象,但是维护跟踪共享的数量 Movie
对象变得笨重。
std::vector<std::shared<Movie>>
进来帮忙。 std::shared_ptr 不仅仅是一个指针,而是一个智能指针,这意味着它将是一个引用计数指针,当所有对该对象的引用超出范围时,它将自行销毁。因此没有内存泄漏,这与您使用原始 Movie*
并以某种方式管理不善不同。
#ifndef ACTOR_H
#define ACTOR_H
#include "Person.hpp"
#include "Movie.hpp"
#include <memory>
class Actor: public Person
{
private:
std::vector<std::shared_ptr<Movie>> movieList;
public:
void addMovie(std::shared_ptr<Movie> newMovie) {this->movieList.push_back(newMovie);}
void printMovies()
{
for(auto& movie: this->movieList)
{
std::cout << movie->getTitle() << '\n';
}
}
};
#endif
然后将 类 的最小化版本和测试 main
函数放在一起:
#include <memory>
#include <vector>
#include <string>
#include <iostream>
class Movie
{
private:
std::string title;
std::string m_rating = "G";
public:
std::string getTitle() const {return this->title;} // const added
void setTitle(std::string newTitle){this->title = newTitle;}
void setRating(std::string rating) { m_rating = rating; }
std::string getRating() const { return m_rating; }
};
class Person {};
class Actor: public Person
{
private:
std::vector<std::shared_ptr<Movie>> movieList;
public:
void addMovie(std::shared_ptr<Movie> newMovie) {this->movieList.push_back(newMovie);}
void printMovies()
{
for(auto& movie: movieList)
{
std::cout << movie->getTitle() << " Rating: " << movie->getRating() << '\n';
}
}
};
int main()
{
// Create our movies
auto movie1 = std::make_shared<Movie>();
auto movie2 = std::make_shared<Movie>();
auto movie3 = std::make_shared<Movie>();
Actor actor1, actor2;
movie1->setTitle("Transformers");
movie2->setTitle("Interstellar");
movie3->setTitle("The Matrix");
actor1.addMovie(movie1);
actor1.addMovie(movie2);
actor2.addMovie(movie1);
actor2.addMovie(movie3);
std::cout << "actor 1 movies:\n";
actor1.printMovies();
std::cout << "\nactor 2 movies:\n";
actor2.printMovies();
// Set the rating to movie1 to "R"
movie1->setRating("R");
std::cout << "\n\nactor 1 movies:\n";
actor1.printMovies();
std::cout << "\nactor 2 movies:\n";
actor2.printMovies();
}
输出:
actor 1 movies:
Transformers Rating: G
Interstellar Rating: G
actor 2 movies:
Transformers Rating: G
The Matrix Rating: G
actor 1 movies:
Transformers Rating: R
Interstellar Rating: G
actor 2 movies:
Transformers Rating: R
The Matrix Rating: G
现在 actor1
和 actor2
实际上共享同一个 Movie
,称为“变形金刚”——它们不再是独立的对象。我添加了 setRating
和 getRating
函数来演示更改 movie1
的评级会将 actor1
和 actor2
的评级更改为 R
。
现在,没有什么能阻止您制作另一部同名电影(例如,movie4
名为“变形金刚”的电影)。如果这是一个问题,您将需要一个额外的数据结构来跟踪已经使用的名称(可能是 std::unordered_set<std::string>
)。但这是一个侧面点,只是为了让你知道这可能会发生。