c++ - 从基调用派生类的虚函数导致 "not a member"错误

标签 c++ compiler-errors virtual

#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 指向的对象,它可能是 AB 或任何类公开派生自 A。编译器只检查指针的类型,并检查被访问的成员是否属于该类。
对于您来说,a1 指向 B 的对象,因此可以像 B 一样对待,但对于编译器 a1A 类型的指针,在编译时它只将其视为 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/

相关文章:

c++ - 通过其抽象基类的指针返回派生类对象

c++ - dlib 的 dcd trainer 的 'warm start' 选项是否只用于 1 类分类?

c++ - 在 GCC 工作正常的情况下使用 Clang 时无限递归模板实例化?

c++ - 以编程方式创建 32 位颜色图标

c++ - 用户定义类中的空指针无效?

c++ - 如何创建虚拟类的 vector ?

c++ - luabind : Accessing an invalidated c++ object from lua results in access violation

android - Dagger 2 with Java 8错误编译

c# - 不包含定义或扩展方法

c++ - 虚拟模板函数的替代方案