#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
的指针吗?
答案 0 :(得分:3)
编译器会告诉您确切的原因:
'getB' : is not a member of 'A'
编译器根据指针的类型进行编译时检查,因为它无法在A
中找到它所报告的方法。请注意,在编译时,编译器可能知道也可能不知道指针a1
指向哪个对象,它可能是A
或B
或公共派生自A
的任何类。编译器只检查指针的类型,并检查被访问的成员是否属于该类
对于您,a1
指向B
的对象,因此可以像B
那样对待,但编译器a1
是A
类型的指针,在编译时,它只将其视为A
。
虽然上面已经详细说明了“为什么这不起作用”的答案,但我认为我应该在“你如何解决这个问题”。
简单的答案是为getB()
实施A
。这通常是正确的做法 - 如果它以某种方式“禁止”在没有此属性的对象上调用getB
,那么就做一些事情 - 打印错误,退出程序,或者其他什么是当有人在代码中出错时(最好在某个地方打印一条消息,然后停止,以便明确出错的地方并且可以调试),这是“正确的”。
替代方案,例如使用动态强制转换,也可以使用。但您仍然必须知道对象是否是B
类 - 或者检查指针是否返回NULL。
虚函数的关键在于,您可以使用派生类中的新变量覆盖基类中的函数。它不支持在派生类中添加NEW函数。支持“新功能”的方法是添加参数:
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;
答案 1 :(得分:1)
您必须在A类中拥有成员函数:
virtual int getB()
{
// do something or not
}
之后,当你致电a1->getB()
时,它将调用B类的成员函数。
另一种方法是在a1上使用dynamic_cast
:
A* a1 = new B(10);
B* b1=dynamic_cast<B*>(a1);
std::cout << b1->getA() << "\t " << b1->getB() << std::endl;
答案 2 :(得分:1)
答案 3 :(得分:0)
虽然a1是指向B类对象的指针,但编译器在运行时才知道a1指向B对象。因此,在编译时,由于A类中没有getB方法,因此会遇到错误。