C++类和虚拟方法

C++ Class and virtual method

本文关键字:方法 虚拟 C++      更新时间:2023-10-16

我有两个关于虚拟方法的问题。

第一:

class Parent
{
public:
    virtual void SHOW(int x = 5) { cout << "PARENT " << x << endl; }
};
class Child : public Parent
{
public:
    virtual void SHOW(int y = 10) { cout << "CHILD " << y << endl; }
};
int main()
{
    Child Y;
    Parent* P = &Y;
    P->SHOW();
    getch();  
    return 0;     
}

我认为 tt 应该是孩子 10,但结果是孩子 5

另一个:

class Parent
{
public:
    virtual void SHOW() { cout << "PARENT" << endl; }
};
class Child : public Parent
{
private:
    virtual void SHOW() { cout << "CHILD" << endl; }
};
int main()
{
    Child Y;
    Parent* P = &Y;
    P->SHOW();
    getch();  
    return 0;     
}

它会在屏幕上显示孩子。我不知道从外面调用的私有方法如何?

谢谢。我正在学习英语,所以..:)

1)C++标准说

虚函数调用 (10.3) 在虚函数的声明中使用默认参数,这些参数由表示对象的指针或引用的静态类型确定。派生类中的重写函数不会从它重写的函数中获取默认参数。

§8.3.6/10

2)在C++中用私有函数覆盖公共虚拟函数

虚函数调用使用虚函数声明中的默认参数,这些参数由用于调用函数的指针的静态类型确定。在您的情况下,P 的静态类型是父级,尽管动态类型解析为子级。这是根据C++标准。

这是一个很好的例子,说明为什么通常最好将虚拟函数设为私有,而将公共函数设为非虚拟函数。赫伯·萨特(Herb Sutter)曾经称之为非虚拟接口习语(NVI)。

让我们将其应用于您的代码。我还将函数名称"SHOW"更改为"show",因为C++中的全大写通常表示宏。此外,我将添加一个虚拟析构函数,因为新手正在阅读这些问题,他们不应该看到没有多态类的多态类。请注意,析构函数是 NVI 的例外。

来吧:

class Parent
{
public:
    void show(int x = 5) { doShow(x); }
    virtual ~Parent() {}
private:
    virtual void doShow(int x) { cout << "PARENT " << x << endl; }
};
class Child : public Parent
{
private:
    virtual void doShow(int x) { cout << "CHILD " << x << endl; }
};

默认参数通常对于使用类对象的代码很有用。然后,该代码使用公共函数。

Parent *p = new Child;
p->show(); // here's where a default argument is a useful feature
delete p;

然而,继承类对完全不同的东西感兴趣,即基类的虚函数。事实证明,当您为子类编写代码时,您很少会觉得需要默认参数。

底线:

  1. 默认参数和虚函数不应混合使用。在斯科特·迈耶斯(Scott Meyers)著名的有效C++书中有一个项目:"永远不要重新定义继承的默认参数值"。你应该读那本书。
  2. 使用 NVI,
  3. 您通常不会遇到此问题,因为事实证明默认参数对于公共函数来说更像是一回事,而对于 NVI,公共函数不是虚拟的。