重载子类中的虚函数

时间:2012-01-11 09:20:18

标签: c++ inheritance virtual

我只是在c ++中使用虚拟关键字和继承概念进行测试。 我写了一个小程序:

#include<stdio.h>
#include<iostream>

using namespace std;

class cna_MO
{
  public:
    virtual void print()
    {
        cout << "cna_MO" << endl;
    }
};

class cna_bsc:public cna_MO
{
  public:
    void print()
    {
        cna_MO::print();
    }

    void print(int a)
    {
        cout << "cna_BSC" << endl;
    }
};

class cna_Mo
{
    cna_MO *_mo;

  public:
    cna_Mo()
    {
        _mo = new cna_bsc;
    }

    virtual void print(int a)
    {
        cout << "cna_Mo with arg" << endl;
        _mo->print(5);
    }

    virtual void print()
    {
        cout << "cna_Mo" << endl;
        _mo->print();
    }
};

int main()
{
    cna_Mo valid_mo;
    cout << "old case is started" << endl;
    valid_mo.print();
    cout << "new case is started" << endl;
    valid_mo.print(5);
    return 0;
}

我在这里做的是我在子类的父类中重载了一个虚函数!这不是正确的做法吗?

我收到编译错误如下:

  

“temp10.cc”,第45行:错误:调用“cna_MO :: print()”时参数太多。

6 个答案:

答案 0 :(得分:23)

从Derived类中的Base类重载函数后,Base类中具有相同名称的所有函数都将隐藏在Derived类中。

将函数cna_bsc::print(int a)添加到派生类后,Derived类的用户将无法再看到函数cna_MO::::print()。这称为函数隐藏。

<强>解决方案: 为了使隐藏函数在派生类中可见,您需要添加:

using cna_MO::print;

在派生类public的{​​{1}}部分。

好读:

<强> What's the meaning of, Warning: Derived::f(char) hides Base::f(double)?

答案 1 :(得分:0)

这是因为子类中的print函数采用参数而原始函数没有。

在cna_MO(父类)中:

virtual void print()

在cna_bsc(子类)中:

void print(int a)

基本上,孩子的打印不应该采用int参数:

void print()

修改

也许最好的做法是传递int可选吗?

例如:

在cna_MO(父类)中:

virtual void print(int a=-1) {
    if (a == -1) {
        // Do something for default param
    } else {
        cout << a;
    }
}

在cna_bsc(子类)中:

void print(int a=-1)

所以如果a == -1你可以假设,他们没有传递任何东西。

诀窍是父和子都需要相同的方法siganture,意思是相同的返回类型和相同的参数类型。

答案 2 :(得分:0)

如果派生类中的函数具有与基类相同的名称和不同的参数,则该函数将隐藏。您可以找到更多信息here ..

您可以通过调用Base::hiddenFun();

来调用特定的隐藏功能

答案 3 :(得分:0)

这是行不通的,因为给定cna_MO *,你可以在编译时看到指向的对象没有(必然)有int重载。如果它实际指向基类对象,_mo->print(5);真的没什么可调用的。还可以有无数个(尚未实现的)派生类,它们不必支持此调用。

  1. 每个派生类必须有print(int) - 在基类中声明它。

  2. 每个派生类都不需要print(int) - cna_Mo仅适用于cna_bsc,因此该成员应为cna_bsc* _mo

答案 4 :(得分:0)

理想情况下,带有int的print应该有不同的名称,但是如果你想让这两个函数都被称为print,那么你应该让它们都是非虚拟的,并使它们成为受保护的虚函数。

class cna_MO 
{   
    public:     
     void print() { doPrint(); }

    protected:
     virtual void doPrint()
      {         cout << "cna_MO" << endl;     
      } 
};  


class cna_bsc:public cna_MO 
{   
    protected:     
       virtual void doPrint()  
                  // although with implementation no need to override it
       {         
            cna_MO::print();     
       } 

    public:
     void print(int a)    
      {
          doPrintInt( a );
      }

    protected:
      virtual void doPrintInt( int )
      {
        cout << "cna_BSC" << endl;     
      } 
 };  

答案 5 :(得分:0)

如果你真的必须这样做,即有一个指向一个类的指针并初始化为派生类,除了在使用它时总是将指针强制转换为正确的类型,别无选择。在这种情况下,((cna_bsc*)_mo)->print(5);