【问题标题】:C++ how to ensure when using virtual inheritance that it calls the inherited and not the base functionC ++如何确保在使用虚拟继承时它调用继承而不是基函数
【发布时间】:2012-03-23 12:14:20
【问题描述】:

我是 C++ 的新手,非常感谢任何和所有帮助。我有这个与类和继承有关的任务。我的理解是,我可以在基类中编写一个虚函数,该虚函数会被继承类中的同名函数覆盖。当我调用任何继承的类时,这工作得很好,但是当我将它们插入一个编写为接收基类的函数时,即使它接收的对象来自继承的类,它也会从继承的类调用初始化程序,但其他仅来自基类的函数。这是我的代码的缩短版本:

基类:

#ifndef PLAYER_CPP
#define PLAYER_CPP
class Player 
{    
protected:
    string playerThrow;
public:
    //function that sets player throw
    void virtual setMove();
    string performMove() {return(playerThrow);}
};
#endif

继承类:

class Avalanche: virtual public Player
{
public:
    Avalanche();    
    //set specific move for class
    void setMove() 
    {
        //always plays rock
        playerThrow = "rock";
    }
};

//initializer, inherit from player, set new name
Avalanche::Avalanche() : Player()
{   
    //initialize name string
    string newName;
    //set name
    newName = "Avalanche Player";
    //sets name in player class
    name = newName;
}

我是如何尝试使用它的:

class Tournament
{
public:
    Tournament();
    Player bout(Player, Player);
    Player Tournament::bout (Player p1, Player p2)
    {
        p1.setMove();
        p2.setMove();
        return p1;
    }
};

最终的结果是将移动设置为空,而不是“摇滚”。

在此先感谢您提供正确方向的任何指示。这个让我很困惑。

-维多利亚

【问题讨论】:

  • 为什么要使用虚拟继承?我看不到任何需要虚拟继承
  • bout 的定义应该在类之外。符合标准的编译器将拒绝此实现。

标签: c++ inheritance polymorphism


【解决方案1】:

您不能将动态绑定与复制传递的参数一起使用。您必须传递引用 (Player&) 或 const 引用 (Player const&) 或指针 (Player*) 或指向 const (Player const*) 的指针。

示例:如果您实例化 Avalanche 并将其传递给接收 Player 的对象,则会发生这种情况:

C++ 看到获得Player 的签名,因此它将使用带有签名的默认复制构造函数创建对象的本地副本Player::Player(Player const&)。这个可以用你的Avalanche参数调用,因为它是从Player继承的公开。尝试隐藏Player 的复制构造函数,以了解发生了什么。

请随时指出您无法理解的事情。

【讨论】:

  • Player const* 不是 const 指针,它是指向 const Player 的指针。
  • 常数不是细节。这很重要。
  • @LuchianGrigore:细节是语言。我完全同意 const 不是一个细节,而且 const 指针与指向 const 的指针完全不同。但请注意模式:“const 引用”是明确的,因为 Foo& const 根本没有意义(因为 const 是隐含的)。在谈论指针时,相同的表述意味着不同的东西。我猜这只是注意力不集中。
  • 两者都不是模棱两可的。 “在谈论指针时,相同的表述意味着不同的东西”不是真的,const 的位置是完全定义的。
  • @LuchianGrigore:我相信我们正在谈论彼此。我在谈论将Foo const& 作为“常量引用”来谈论是多么普遍。虽然相同的语言模式应用于指针,而不是引用“const 指针”(与“指向 const 的指针”相对)实际上并不意味着 Foo const* 而是 Foo* const。这一点,再加上中午注意力不集中,导致我写了“const 指针”,而我实际上的意思是“指向 const 的指针”:)
【解决方案2】:

您将Player 对象传递给bout,因此您没有利用多态性。

你应该传递指针或引用:

Player bout(Player*, Player*);
//or
Player bout(Player&, Player&);

请注意,在您的版本中,如果您将 Avalanche 对象传递给方法,您将遇到对象切片(查找)。

【讨论】:

  • 只有当他们可以是nullptr。如果没有,参考文献会更好。
  • 感谢关于对象切片的提示,我确实遇到了这个问题。
【解决方案3】:

当您调用Tournament::bout 时,您从传入的Avalanche 对象构造了两个新的Player 对象。

Player 构造函数不知道它正在复制/移动的对象的 Avalanche 部分,因此只复制 Player 部分。

p1p2Players,因此它们的行为类似于 Players,而不是 Avalanches。

如果您不想构造新的Player 对象,则通过引用传递参数:

Player& Tournament::bout (Player& p1, Player& p2)
{
    p1.setMove();
    p2.setMove();
    return p1;
}

【讨论】:

    猜你喜欢
    • 2017-03-31
    • 2013-01-26
    • 2015-06-21
    • 2011-10-03
    • 1970-01-01
    • 2016-03-26
    • 2011-01-08
    相关资源
    最近更新 更多