Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在派生类之间复制构造函数_C++_Oop_Abstract Class_Copy Constructor - Fatal编程技术网

C++ 在派生类之间复制构造函数

C++ 在派生类之间复制构造函数,c++,oop,abstract-class,copy-constructor,C++,Oop,Abstract Class,Copy Constructor,如何将派生类复制到另一个派生类 我在术语上有缺陷,所以我将试着用一个例子来说明 我们正在用电脑和人玩纸牌游戏。卡片和命令是其他类 class Player { Card *Hand[4]; // etc... }; class Human: public Player { Command getCommand(); void PlayCard(Card card); void quit(); // etc... }; class Compute

如何将派生类复制到另一个派生类

我在术语上有缺陷,所以我将试着用一个例子来说明

我们正在用电脑和人玩纸牌游戏。卡片和命令是其他类

class Player
{
    Card *Hand[4];
    // etc...
};

class Human: public Player
{
    Command getCommand();
    void PlayCard(Card card);
    void quit();
    // etc...
};

class Computer: public Player
{
    Command ai();
    void PlayCard(Card card);
    // etc...
};
在我们的主要功能中的某个地方

// ...
Human p1; // Assume initialized and usable.
if(p1.getCommand() == QUIT)
{
    cout << "PLAYER 1 RAGEQUITS WHAT A NOOB LOL << endl;
    cout << "A COMPUTER WILL NOW TAKE OVER." << endl;
    p1.quit()
    p1 = new Computer(); // THE IDEA BEING THAT WE WANT TO PRESERVE p1's MEMBERS.
}
// ...

我们需要删除/释放主目录中的任何内容吗

您可以使用构造函数。对于这种特殊情况,我可能会有一个名为“CopyGameState”的方法。

复制构造函数用于将现有对象复制到同一类的新实例中


您需要的是赋值运算符(
运算符=
),它允许将不同类型的值赋值给现有的类对象。

它不是复制构造函数,而是转换构造函数。比如:

Computer::Computer(const Player& had_to_go) : Player(had_to_go) {}
p1.quit();
Computer* replacement = new Computer(p1);
delete p1;
p1 = replacement;
这将使用
Player
的复制构造函数来保留公共基类中的成员

当然,您最好让
Player::Player(constplayer&)
正确地工作,遵循和所有

最后,您将执行以下操作:

Computer::Computer(const Player& had_to_go) : Player(had_to_go) {}
p1.quit();
Computer* replacement = new Computer(p1);
delete p1;
p1 = replacement;

这里有一个设计问题。如果您想在维护公共成员变量的同时将玩家从人切换到计算机,那么您应该以这种方式构造类

class Player
{ 
public:
    friend class Human;    // These friends are necessary if the controllers
    friend class Computer; // need access to Player's private data.

    Card hand[4];
    Controller* controller;
};

class Controller
{
public:
    virtual Command getCommand(Player const&) = 0;
};

class Human : public Controller
{
public:
    Command getCommand(Player const&) { /* get command from user input */ }
};

class Computer : public Controller
{
public:
    Command getCommand(Player const&) { /* get command from AI */ }
};
然后,当您需要从人切换到计算机时,只需更改控制器

p1->controller = new Computer();

这样,卡将被维护,只有控制机制将被更改。

好消息:您拼写的“术语”正确:)它是
class
,而不是
class
;和
public
,而不是
public
,这是另一种合理的方法,尽管
控制器
可能需要以某种方式读取
播放器
的私有数据。在这种情况下,播放器可以公开该数据,也可以让控制器成为播放器的朋友。这就是朋友的作用:)这不仅仅是访问说明符的问题,还需要一个指向实例的指针。但这也很容易解决。@Ben Voigt:是的,刚刚意识到这就是你的意思。我已经将Player ref添加到getCommand调用:-)只需添加一个Player上下文并向控制器传递一个对它的不可变引用。这是完全向后的,因为它不会替换vtable。@Ben-您不能替换构造类的vtable。除非创建一个新对象,否则。。。这就是为什么赋值运算符不是一个好的解决方案。他需要一个新的对象和一个新的vtable。@Ben-他需要重新设计。直到我读了Peter的答案后,我才清楚地理解真正的问题是什么。他希望
p1->PlayCard()
开始使用
Computer::PlayCard
,而不是
Human::PlayCard
,同时保持会员数据的完整性。不管是@Peter的答案还是我的答案都能让他达到目的。你能给我解释一下“三法则”是什么吗:P,也是Player::Player(const-Player&)Player的复制构造函数吗?@Ir-Win:是的,它是
Player
的复制构造函数,三法则说如果你有自定义的复制构造函数、赋值运算符或析构函数,你需要这三个。在这种情况下,这是因为
播放器
中存储了
卡*
。编译器提供的副本将复制指针,这意味着您最终将删除它两次。不好的。在C++-FAQ标签中有一个很好的解释。我将从我的答案中添加一个链接。