我有以下类别:
class A {
public:
virtual void f() {}
};
class B : public A{
public:
void f(int x) {}
};
如果我说
B *b = new B();
b->f();
编译器错误说C2660:“B :: F”:函数不接受0参数。 不应该在B中的函数重载它,因为它是一个虚函数? 不要虚函数得到隐藏的这样吗?
编辑 :我确实打算从A,其中显示了相同的行为继承B中。
我有以下类别:
class A {
public:
virtual void f() {}
};
class B : public A{
public:
void f(int x) {}
};
如果我说
B *b = new B();
b->f();
编译器错误说C2660:“B :: F”:函数不接受0参数。 不应该在B中的函数重载它,因为它是一个虚函数? 不要虚函数得到隐藏的这样吗?
编辑 :我确实打算从A,其中显示了相同的行为继承B中。
假设你打算B
从派生A
:
f(int)
和f()
是不同的签名,因此,不同的功能。
您可以覆盖与具有兼容签名,这意味着要么相同签名,或在其中返回类型是“更具体的”的功能的虚拟功能(这是协方差)。
否则,你的派生类函数隐藏的虚拟功能,就像在那里派生类中声明函数具有相同的名称作为基类的功能的任何其它情况。 你可以把using A::f;
在B级取消隐藏名称
或者,也可以把它作为(static_cast<A*>(b))->f();
或作为b->A::f();
。 不同的是,如果B
实际上不会覆盖f()
,那么前者呼叫的倍率,而后者调用函数A
不管。
B类不从所以没有函数F导出()是否存在。 你大概的意思是:
class A {
public:
virtual void f() {}
};
class B : public A {
public:
void f(int x) {}
};
编辑:我错过了实际功能隐藏。 见史蒂夫·杰索普答案更透彻的解释。
没有,是的,分别。 如果你想超载行为,你需要说
using A::f;
在B.
B不从A派生,正确的声明是:
class B : public A
当编译器解析符号的方法不止一种,它必须选择哪一个具有优先权,除非代码告诉它,否则。 什么你期望是优先于压倒一切的超载。 (完了,完了,完了,aaaaack!对不起,得到了“over'whelmed)。
这个例子中有乙继承其中子类提供一个重载版本的虚拟方法。 重载是使用同样的方法名称但不同的签名在同一个类中的方法。 由于B是A的子类,则重写f()的,这意味着它不能同时在同一时间的过载。 这就是为什么它被隐藏。
对于类A,声明方法
virtual void f() {}
虚拟意味着方法使用一组特定的不与你B的声明一致的规则来解决。
B *b = new B();
通过创建“B”为“B”的一个实例,编译器没有必要使用相同的名称的方法的虚拟性质在“A”。
如果你已经宣布“B”这样的
B *b = new A();
然后该呼叫B-> F(); 通过利用虚拟的分辨率确实会参考的方法,在。
看来,它存在与Biern Stroustrup的常见问题的答案,而类似的问题: http://www.stroustrup.com/bs_faq2.html#overloadderived
正如他所说的:
“在C ++中,有跨范围没有超载”
但如果你想
“这很容易使用using声明完成”