我只是在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()”时参数太多。
答案 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);
真的没什么可调用的。还可以有无数个(尚未实现的)派生类,它们不必支持此调用。
每个派生类必须有print(int)
- 在基类中声明它。
每个派生类都不需要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);