在这种情况下复制很棘手,因为您必须始终确保Persons 引用正确的World。一种选择是确保您在World 中有自定义复制构造函数和operator=,您可以在其中调用函数来更新您的人口。像这样的:
#include <iostream>
#include <vector>
#include <string>
#include <functional>
using uint = unsigned int;
class World;
using WorldRef = std::reference_wrapper<World>;
class Person
{
WorldRef world;
std::string name;
friend class World;
public:
Person(World& _world,
const std::string& _name)
:
world(_world),
name(_name)
{}
};
class World
{
uint year;
std::string name;
std::vector<Person> population;
friend class Person;
void init()
{
for (auto& p : population)
{
/// Note: This is necessary, otherwise this world's
/// inhabitants will refer to the wrong world.
/// Call this function from each constructor and
/// assignment operator.
p.world = std::ref(*this);
}
}
public:
World(const uint _year,
const World& _other,
const std::string& _name)
:
year(_year),
population(_other.population),
name(_name)
{
init();
std::cout << "It is now " << year << "\n"
<< "Melon Tusk has built a rocket allowing cheap interplanetary travel.\n";
for (auto& p : population)
{
std::cout << p.name << " has moved to " << p.world.get().name << "\n";
}
}
World(const uint _year,
const std::string& _name,
const uint _pop_size)
:
year(_year),
name(_name),
population(_pop_size, {*this, "Anonymous " + _name + "ling"})
{
init();
std::cout << "It is " << year << "\n";
std::cout << name << " has " << population.size() << " inhabitants:\n";
for (const auto& p : population)
{
std::cout << p.name << "\n";
}
}
void operator = (const World& _other)
{
population = _other.population;
init();
}
void set_name(const std::string& _name)
{
name = _name;
}
std::string get_name() const
{
return name;
}
void add_person(const std::string& _name)
{
population.emplace_back(*this, _name);
std::cout <<_name << " was born on " << name << "\n";
}
uint population_size() const
{
return population.size();
}
};
int main()
{
World earth(2018, "Earth", 5);
World mars(2025, earth, "Mars");
mars.add_person("Alice");
mars.add_person("Bob");
mars.add_person("Carol");
World europa = mars;
europa.set_name("Europa");
std::cout << "Everyone has moved on to " << europa.get_name() << "\n";
europa.add_person("David");
std::cout << europa.get_name() << " has a population of " << europa.population_size() << "\n"
<< "A war is brewing over scant resources.\n"
<< "Such is the nature of humanity.\n";
return 0;
}
打印出来
It is 2018
Earth has 5 inhabitants:
Anonymous Earthling
Anonymous Earthling
Anonymous Earthling
Anonymous Earthling
Anonymous Earthling
It is now 2025
Melon Tusk has built a rocket allowing cheap interplanetary travel.
Anonymous Earthling has moved to Mars
Anonymous Earthling has moved to Mars
Anonymous Earthling has moved to Mars
Anonymous Earthling has moved to Mars
Anonymous Earthling has moved to Mars
Alice was born on Mars
Bob was born on Mars
Carol was born on Mars
Everyone has moved on to Europa
David was born on Europa
Europa has a population of 9
A war is brewing over scant resources.
Such is the nature of humanity.
注意我们如何在每个构造函数中调用init() 和operator=。根据您的需要,可能有一种更简洁的方法。
附:我不确定从逻辑角度复制 World 对象意味着什么,因为您最终会得到Persons 的克隆。也许这正是您想要的,但我只是想提一下。