在Visual C ++ 2010上运行此C ++源:
class B{
public:
virtual void f(int a){}
virtual void f(){}
};
class A:public B{
public:
virtual void f(int a){}
};
int main(){
A a;
a.f();
return 0;
}
导致以下错误:
IntelliSense: too few arguments in function call
换句话说,似乎void f()
没有继承?
有什么问题?
答案 0 :(得分:7)
似乎void f()没有继承?
A类中的名称f 阴影在B中命名为f。您仍然可以通过这种方式从B访问foo()
A a;
a.B::f();
其他选项是在A:
的范围内重新声明B的函数fooclass A : public B{
public:
virtual void f(int a) {}
using B::foo;
};
C ++标准版n3337 § 10.2会员名称查找
1)成员名称查找确定名称的含义(id-expression) 在一个范围内(3.3.7)。名称查找可能导致歧义 在哪种情况下,该计划是不正确的。对于id-expression,名称 查询从此类的范围开始;对于限定ID,名称 查询从嵌套名称说明符的范围开始。名称查找 在访问控制之前进行(3.4,第11条)。
2)以下步骤定义成员的名称查找结果 在类范围C中命名为f。
3)C中f的查找集,称为S(f,C),由两个组成 组件集:声明集,一组名为f的成员;和 子对象集,一组子对象,其中声明了这些成员 (可能包括使用声明)被发现。在宣言中 set,using-declarations由他们指定的成员替换, 和类型声明(包括inject-class-names)替换为 他们指定的类型。 S(f,C)计算如下:
4)如果C包含名称为f的声明,则声明集 包含在C中声明的满足f的每个声明 查找发生的语言构造的要求。 [ 注意:在精心设计的类型说明符(3.4.4)或中查找名称 例如,base-specifier(第10条)忽略所有非类型 声明,同时在嵌套名称说明符中查找名称 (3.4.3)忽略函数,变量和枚举器声明。如 另一个例子,在using声明中查找名称(7.3.3) 包括声明的类或枚举 通常被该名称的另一个声明所隐藏 范围。 - 结束注释]如果生成的声明集不为空,则为 子对象集包含C本身,计算完成。
5)否则(即C不包含f或f的声明) 结果声明集为空),S(f,C)最初为空。如果是C. 有基类,计算每个直接基数中f的查找集 class subobject Bi,依次合并每个这样的查找集S(f,Bi) 进入S(f,C)。
答案 1 :(得分:5)
您的A::f(int a)
声明会隐藏所有签名B::f
,除非它们暴露给派生类。曝光“隐藏”方法有两个很好的选择。
选项1
class A:public B{
public:
using B::f;
virtual void f(int a){}
};
选项2
class A:public B{
public:
virtual void f(int a){}
virtual void f(){ B::f(); }
};
答案 2 :(得分:0)
1)你必须使用指针。 2)如果你想获得A :: f(),你必须使用A *类型变量,但类实例可以是B *或A *类型。
#include <iostream>
using namespace std;
class A {
public:
virtual void f(int a) {cout << a << " A::f(int)" << endl; }
virtual void f(){cout << 5 << " A::f()" << endl;}
};
class B:public A {
public:
virtual void f(int a) {cout << a+1 << " B::f(int)" << endl; }
};
int main() {
A *a;
a = new B();
a->f(1);
a->f();
delete a;
a = new A();
a->f(1);
a->f();
delete a;
return 0;
}
输出:
2 B::f(int)
5 A::f()
1 A::f(int)
5 A::f()