好吧,也许我的回答有点过头了,我知道这并不是你真正要问的,但它可以帮助你理解为什么船舶中的价值受到保护,而且我似乎有太多时间了。
由于围绕具有共同方法和属性的船舶/怪物/对象构建游戏是一个非常常见的问题,因此有一种非常常见的方法来实现这一点。它基于三级继承。
1.界面
它将定义可以从外部调用的方法,它是一个契约。从它继承的每个类必须实现这些方法。
在你的情况下,一个基本的看起来像这样:
class IShip
{
public:
virtual ~IShip() // needs this, see link below
{ std::cout << "Interface destructor called" << std::endl; }
virtual std::string type() = 0;
virtual int size() = 0;
virtual int hits() = 0;
virtual void specialMove() = 0;
};
Reason 用于虚拟 dtor。
2。摘要
它继承自这个接口,并实现了每艘船都可以重用的基本方法,可以这样做:
class AShip : public IShip
{
public:
AShip(std::string type, int size, int hits)
: _type(type)
, _size(size)
, _hits(hits)
{ std::cout << "Abstract constructor called" << std::endl; }
virtual ~AShip() // still needs this
{ std::cout << "Abstract destructor called" << std::endl; }
virtual inline std::string type() // inline keyword to put the code in-place instead of calling it
{ return _type; } // should only do this on very small methods
virtual inline int size() // virtual are not necessary
{ return _size; } // but it's best practice to clarify code
virtual inline int hits()
{ return _hits; }
// -- need overload method
virtual void specialMove() = 0;
// -- protected since it needs to be accessible from child classes
protected:
std::string _type;
int _size;
int _hits;
};
此时你不能实例化任何东西,因为这两个类都是虚拟的。 More about virtual classes
接口是一个纯虚拟类(因为定义的每个方法都有'= 0')。
3.实例化
您现在可以做的是轻松实现多个继承自 AShip 但仍指定一些特殊的类,您是对的,我说的是 specialMove,我将为为了我的例子:
class TheDestructor : public AShip
{
public:
TheDestructor()
: AShip("The Destructor", 20, 100)
, _attack("DestructionOver9000")
{ std::cout << "TheDestructor constructor called" << std::endl; }
virtual ~TheDestructor() // still needs this to help the compiler
{ std::cout << "TheDestructor destructor called" << std::endl; }
inline void specialMove() // specialMove overload
{ std::cout << "Attack " << _attack << " from " << _type << std::endl; }
private:
std::string _attack;
};
class MyPunyShip : public AShip
{
public:
MyPunyShip()
: AShip("My Puny Ship", 1, 1)
, _escape("just fly away as fast as he can...")
{ std::cout << "MyPunyShip constructor called" << std::endl; }
virtual ~MyPunyShip() // still needs this to help the compiler
{ std::cout << "MyPunyShip destructor called" << std::endl; }
inline void specialMove() // specialMove overload
{ std::cout << _type << " " << _escape << std::endl; }
private:
std::string _escape;
};
现在让我们测试一下已经做了什么:
int main()
{
std::map<std::string, IShip*> ships;
ships.insert(std::make_pair("The Destructor", new TheDestructor));
std::cout << std::endl;
ships.insert(std::make_pair("My Puny Ship", new MyPunyShip));
std::cout << std::endl;
for (std::map<std::string, IShip*>::iterator itS = ships.begin() ; itS != ships.end() ; ++itS)
{
// *itS to access the data of the iterator
// second to access the second member of the pair
std::cout << "type: " << (*itS).second->type() << "\n";
std::cout << "size: " << (*itS).second->size() << "\n";
std::cout << "hits: " << (*itS).second->hits() << "\n";
std::cout << std::endl;
}
ships["The Destructor"]->specialMove();
ships["My Puny Ship"]->specialMove();
}
您只能调用接口中的方法,因为地图中的类型是 IShip,但它允许您实现具有不同统计数据的各种船。
让我们看看输出...
输出:
Abstract constructor called
TheDestructor constructor called
Abstract constructor called
MyPunyShip constructor called
type: My Puny Ship - size: 1 - hits: 1
type: The Destructor - size: 20 - hits: 100
Attack DestructionOver9000 from The Destructor
My Puny Ship just fly away as fast as he can...
但是,但是……有些东西不见了对吧?
有些东西似乎很奇怪......什么???我忘了用删除??
好吧,我忘了使用 c++11 作为一个整体来使示例更小,并保持我试图传达的内容清晰。我应该在这里使用std::unique_ptr 或std::shared_ptr。
'new' main 看起来像这样,并在启用 c++11 标志的情况下编译:
int main()
{
std::map<std::string, std::shared_ptr<IShip>> ships;
ships.emplace(std::make_pair("The Destructor", std::shared_ptr<IShip>(new TheDestructor)));
ships.emplace(std::make_pair("My Puny Ship", std::shared_ptr<IShip>(new MyPunyShip)));
for (auto ship : ships) // damn that's neat...
{
std::cout << "type: " << ship.second->type() << " - ";
std::cout << "size: " << ship.second->size() << " - ";
std::cout << "hits: " << ship.second->hits() << "\n";
}
ships["The Destructor"]->specialMove();
ships["My Puny Ship"]->specialMove();
}
输出:
Abstract constructor called
TheDestructor constructor called
Abstract constructor called
MyPunyShip constructor called
type: My Puny Ship - size: 1 - hits: 1
type: The Destructor - size: 20 - hits: 100
Attack DestructionOver9000 from The Destructor
My Puny Ship just fly away as fast as he can...
TheDestructor destructor called
Abstract destructor called
Interface destructor called
MyPunyShip destructor called
Abstract destructor called
Interface destructor called
哇,我非常想念你 c++11。开个玩笑,你可以看到我们的 IShip* 指针会自动调用析构函数,如果你问我,这很好。
为什么接口和抽象似乎都做得过火了?我对此的看法是,一个人可能需要 IVehicle,但创建 AShip、ACar、ASpaceCraft 等......但有不同的限制。但这是一个非常有效的问题,您应该调整这种“模式”以适应您的需求和理念。
希望它能帮助你理解一些关于 c++/c++11 和继承的概念,下一步是为你构建一个factory ;)