c++ - 我应该如何实现现有父对象的临时子对象?
问题描述
我知道这个问题听起来很奇怪,所以让我从这些问题开始:
问题 1
我正在制作一个大富翁游戏(Monopoly
已经制作了一个有PlayerList
成员的类,包含玩家),并且我已经实现了一个Auction
类。最近发现自己的Auction
class和PlayerList
class里面有很多可比的代码,所以在class里面放了很多Auction
-code BidderList
。
// Auction.cpp
Auction::Auction(Property* property, PlayerList* bidderList, int currBidderIndex)
: m_property{ property }, m_bidderList{ new BidderList(bidderList, currBidderIndex) },
m_highestBid{ startBid }, m_previous_has_left{ false }
{
}
// BidderList.cpp
BidderList::BidderList(PlayerList* playerList, int currBidderIndex)
: PlayerList(playerList)
{
m_currPlayerIndex = currBidderIndex;
}
但是...在我的拍卖实现中,它被用作临时对象,完成后将被销毁。(是的,我可以给它设置器。)由于我使用的是原始播放器对象(需要修改它们),所以当BidderList
对象被破坏时,我也会(无意地)删除基本析构函数中的那些:
PlayerList::~PlayerList()
{
for (const auto player : m_players)
delete player;
}
...这迫使我做这样的事情:
// Prevent base class from deleting the players! - not so clean
BidderList::~BidderList()
{
int size = getSize();
for (int i = 0; i < size; ++i)
m_players[i] = nullptr;
}
我仍然想在拍卖后使用我的球员,因为不确定比赛是否会结束。我想知道我是否可以以更清洁的方式做到这一点。
问题 2
我也在考虑从 Player 类中派生Bidder
和 ( Trader
for Trade
)(这并没有以任何明显的方式解决前面的问题),因为这样我可以再次获得更高的凝聚力。尽管在这种情况下问题不大,但我仍然想知道以下问题的答案:
不知何故,每个玩家都在拍卖期间充当竞标者(这仍然是暂时的)。
- 我可以将每个玩家复制到投标者中,但是我不会修改实际的玩家(当然,这是我想要的)。
- 我可以让 Bidder 包含一个指向实际对象的指针,这意味着我必须将 Player 的每个方法重新链接到投标者,我实际上应该使用继承。
如果我设法将实际玩家转换为投标人(所以我将使用原始玩家对象),那么我仍然必须确保只有派生类被销毁 - 对我来说听起来像是虚构的。那么这里使用复合关系就没有其他方法了吗?因为,它看起来像这样,它并不漂亮:
bool Derived::foo()
{
return m_base.foo();
}
在这两个问题中,我都需要一个临时派生类,由现有的父类构建,之后需要以安全的方式对其进行清理。你能帮我在这里做出正确的决定吗?(是的,我确实想将拍卖对象保留为临时对象,只是为了练习)。提前致谢!
解决方案
我考虑std::shared_ptr<Object>
了一段时间,我想我已经找到了第二个问题的解决方案,尽管它仍然有一点缺点,即每个需要在子类中修改的成员都必须是 a shared_ptr
,即使你不会不要让它成为一个指针。请参阅下面的代码,代表假期员工的课程。
人
/* - - - - - - - HEADER- - - - - - - -*/
#pragma once
#include <string>
#include <memory>
class Person
{
public:
Person(std::string name, int capital = 1000);
std::string getName() const;
virtual void print() const = 0;
protected:
std::string m_name;
std::shared_ptr<int> m_capital;
};
/* - - - - - - - SOURCE- - - - - - - -*/
#include "Person.h"
#include <iostream>
Person::Person(std::string name, int capital)
: m_name{ name }, m_capital{ std::shared_ptr<int>(new int{capital}) }
{
}
std::string Person::getName() const
{
return m_name;
}
员工
/* - - - - - - - HEADER- - - - - - - -*/
#pragma once
#include "Person.h"
class Employee : public Person
{
public:
Employee(std::string name, std::string workName);
std::string getWorkName() const;
void print() const override;
private:
std::string m_workName;
};
/* - - - - - - - SOURCE- - - - - - - -*/
#include "Employee.h"
#include <iostream>
Employee::Employee(std::string name, std::string workName)
: Person(name), m_workName{ workName }
{
}
std::string Employee::getWorkName() const
{
return m_workName;
}
void Employee::print() const
{
std::cout
<< m_name << '\n'
<< " I'm an employee at " << m_workName << '\n'
<< " I have a capital of " << std::to_string(*m_capital) << '\n'
;
}
游客
/* - - - - - - - HEADER- - - - - - - -*/
#pragma once
#include "Person.h"
#include <queue>
class Tourist : public Person
{
public:
Tourist(std::string name, std::queue<std::string> destinations);
Tourist(const Person& person, std::queue<std::string> destinations);
void visitNextDestination();
void print() const override;
private:
std::queue<std::string> m_destinations;
};
/* - - - - - - - SOURCE- - - - - - - -*/
#include "Tourist.h"
#include <iostream>
Tourist::Tourist(std::string name, std::queue<std::string> destinations)
: Person(name), m_destinations{destinations}
{
}
Tourist::Tourist(const Person& person, std::queue<std::string> destinations)
: Person(person), m_destinations{destinations}
{
}
void Tourist::visitNextDestination()
{
if (m_destinations.size() > 0) {
m_destinations.pop();
*m_capital -= 100;
}
}
void Tourist::print() const
{
std::cout
<< m_name << '\n'
<< " I'm a tourist heading for " << m_destinations.front() << '\n'
<< " I have a capital of " << std::to_string(*m_capital) << '\n'
;
}
主文件
#include "Employee.h"
#include "Tourist.h"
int main()
{
std::queue<std::string> destinations;
destinations.push("Paris");
destinations.push("London");
destinations.push("Berlin");
std::vector<Person*> persons{
new Employee{"Harry", "Microsoft"},
new Employee{"Frank", "Apple"},
new Tourist{"Bob", destinations}
};
for (const auto person : persons)
person->print();
Tourist* frank = new Tourist{ *persons[1], destinations };
frank->visitNextDestination();
frank->print();
delete frank;
persons[1]->print();
}
输出
Harry
I'm an employee at Microsoft
I have a capital of 1000
Frank
I'm an employee at Apple
I have a capital of 1000
Bob
I'm a tourist heading for Paris
I have a capital of 1000
Frank
I'm a tourist heading for London
I have a capital of 900
Frank
I'm an employee at Apple
I have a capital of 900
推荐阅读
- android - ImageView 滑块中的 MediaPlayer 释放问题
- angular - 如何使用 Angular 9 中的 Angular 材料制作持久对话框(模态框)?
- php - 从 MySQL 字段中拆分记录
- javascript - 这个对 WeatherApi 的请求有什么问题
- python - Is it possible to use request.POST as a dictionary input?
- c++ - file.open 不在 C++ 中创建新文件
- javascript - 如何在角度 8 中从一个组件访问另一个组件的 div id
- javascript - 在 D3.js 中使用带有转换的回调函数
- javascript - 我是否必须在 React with typescript 中的可重用输入上声明占位符?
- javascript - 从变量中获取对象元素