【问题标题】:C++ Class and virtual methodC++ 类和虚方法
【发布时间】:2014-04-06 14:09:06
【问题描述】:

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

第一:

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 应该是 CHILD 10 但结果是 CHILD 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;     
}

它会在屏幕上显示 CHILD。不知道怎么从外部调用的私有方法?

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

【问题讨论】:

  • 默认值不会被继承,即使函数是虚拟定义的。它们被解析为变量(在本例中为父类)的 static 类型的默认值。至于倒数第二段关于私有方法的问题,你是什么意思?
  • CHILD's SHOW 是一个私有方法。为什么可以从 P->SHOW() 调用

标签: c++ class virtual private


【解决方案1】:

1) C++ 标准说

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

§8.3.6/10

2) Overriding public virtual functions with private functions in C++

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      这是一个很好的例子,说明为什么最好将虚拟函数设为私有而将公共函数设为非虚拟。 Herb Sutter 曾将其称为Non-Virtual Interface Idiom (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 著名的Effective C++ 书中有一个条目:“永远不要重新定义继承的默认参数值”。你应该读那本书。
      2. 使用 NVI,您通常不会遇到这个问题,因为事实证明默认参数更多地用于公共函数,而使用 NVI,公共函数不是虚拟的。

      【讨论】:

      • 虽然这无疑是解决这个问题的一个非常优雅的解决方案,但我不同意你认为 NVI 应该在任何地方使用。在某些情况下它的使用是有用的并且产生更清洁/更安全的代码,但一般说不能声明公共虚拟方法是错误的 IMO
      • 我并不是说你应该在任何地方都使用它。但我是说它应该是默认值。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-01
      • 2017-05-24
      • 2012-12-21
      • 2011-02-01
      • 1970-01-01
      • 2014-10-25
      • 1970-01-01
      相关资源
      最近更新 更多