C ++如何确保在使用虚拟继承时它调用继承而不是基函数

Posted

技术标签:

【中文标题】C ++如何确保在使用虚拟继承时它调用继承而不是基函数【英文标题】:C++ how to ensure when using virtual inheritance that it calls the inherited and not the base function 【发布时间】: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;
    
;

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

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

-维多利亚

【问题讨论】:

见:***.com/questions/274626/… 为什么要使用虚拟继承?我看不到任何需要虚拟继承 bout 的定义应该在类之外。符合标准的编译器将拒绝此实现。 【参考方案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;

【讨论】:

以上是关于C ++如何确保在使用虚拟继承时它调用继承而不是基函数的主要内容,如果未能解决你的问题,请参考以下文章

在java中子类若要继承父类,需要使用的关键字是啥

涉及依赖注入时如何使用组合而不是继承?

(C ++)如何在继承子类后删除基类?

C++--继承中的构造与析构父子间的冲突

C++/MFC多重继承调用基类构造函数

如何继承继承的方法而不是覆盖继承的方法?