#include<iostream>
class A {
private :
int _a;
public :
A(int i=0) : _a(i){}
virtual void setA(int i) { _a = i;}
virtual int getA(){ return _a;}
};
class B : public A
{
private :
int _b;
public :
B(int i) : _b(i){}
virtual void setB(int i) { _b = i;}
virtual int getB(){ return _b;}
};
int main(){
A* a1 = new B(10);
std::cout << a1->getA() << "\t " << a1->getB() << std::endl;
return 0;
}
编译时出现以下错误:
test.cpp(28): error C2039: 'getB' : is not a member of 'A'
a1
不应该得到 getB
因为它实际上是指向 B
的指针吗?
最佳答案
编译器告诉你确切的原因:
'getB' : is not a member of 'A'
编译器根据指针的类型 进行编译时检查,因为它无法在A
中找到它报告的方法。请注意,在编译时,编译器可能知道也可能不知道指针 a1
指向的对象,它可能是 A
或 B
或任何类公开派生自 A
。编译器只检查指针的类型,并检查被访问的成员是否属于该类。
对于您来说,a1
指向 B
的对象,因此可以像 B
一样对待,但对于编译器 a1
是 A
类型的指针,在编译时它只将其视为 A
。
虽然上面很好地回答了“为什么这不起作用”,但我认为我应该关注“你如何解决这个问题”。
简单的答案是为A
实现一个getB()
。这通常是正确的做法 - 如果以某种方式“禁止”在不具有此属性的对象上调用 getB
,然后做一些事情 - 打印错误,退出程序,或者当有人在代码中做错了什么时“正确”的任何东西(最好在某处打印一条消息,然后停止,这样就清楚出了什么问题并且可以调试)。
替代方案,例如使用动态转换,也可以工作。但是您仍然必须知道对象是否是 B
类 - 或者检查指针是否返回 NULL。
虚函数的全部意义在于,您可以使用派生类中的新变体覆盖基类中的虚函数。它不支持在派生类中添加新函数。支持“新功能”的方式是例如添加一个参数:
class A
{
public:
...
virtual int get(char v)
{
if (v == 'A') return _a;
else
{
std::cerr << "Error: Requesting invalid variable: '" << v << "'" << std::endl;
return -1;
}
}
...
}
class B: public A
{
...
virtual get(char v)
{
if (v == 'B')
return b;
return A::get(v);
}
...
}
现在稍微修改一下就可以了:
std::cout << a1->get('A') << "\t " << a1->get('B') << std::endl;
关于c++ - 从基调用派生类的虚函数导致 "not a member"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15718374/