C ++虚方法重载/覆盖编译器错误

时间:2012-01-30 21:33:11

标签: c++ visual-c++

我正在用C ++编写一个小程序,我在多态中玩什么 所以代码是这样的:

//Base.h
class Base{
    public:
        void method(const objectType1& stuff1); 
        //objectType1 is whatever type you what (int, string, ...)

    protected:      
        Base(void);
        virtual ~Base(void);

        virtual void method(void) = 0;
};

//Derived.h
/*FINAL - DO NOT INHERIT THIS CLASS OR YOU WILL die :)*/
class Derived : public Base{
    public:
        Derived(void);
        ~Derived(void);

    private:
        void method(void);
};


//Main.cpp
int main(){
    objectType1 ot1;

    //this code works
    Base *bd = new Derived;
    bd->method(ot1);

    //this dosen't
    Derived *dd = new Derived;
    dd->method(ot1); 
    // he doesn't call Base::method(const objectType1& stuff1),
    // he calls Derived::method(void)

    return 0;
}

我通过在其他方面重命名虚拟方法void method(void)解决了这个问题,一切都很顺利。

我的问题是:

  • 为什么编译器不知道从基类调用该方法?
  • 为什么我在void method(void)中看到main,因为protected中的Baseprivate中的Derived被声明为{{1}}? (这是某种副作用)

谢谢:)。

2 个答案:

答案 0 :(得分:3)

基类中的成员方法是public,这意味着任何一段代码都可以调用它。除了是公共的,它是虚拟的,这意味着执行将在运行时动态分派到最终的覆盖。

在调度调度的引用/指针的静态类型中检查静态 ,即使它将动态调度。

另一方面,在第二种情况下,调用是通过派生类型,并且在该级别检查访问说明符,其中编译器发现成员函数为private并因此抱怨。

简单来说,当对象用作基础时,它表现为基础,但直接使用时,它的行为就像派生一样。

答案 1 :(得分:1)

Derived中的方法定义隐藏了Base中的定义。为避免这种情况,请将using Base::method;添加到Derived

这是因为在Derived中调用函数时,只有在Base中的名称不正确时,编译器才会查看Derived。请注意,它不会查找签名,而只会查找该阶段中的名称。基于签名的过载分辨率仅在之后完成。这实际上与以下情况没有太大区别:

void function(int);
void function();

int main()
{
  void function(); // this declaration hides *both* global declarations
  function(3); // error
}

在您的情况下,Base扮演全局范围的角色,Derived扮演功能范围的角色。

另请注意,这与virtaul fgunctions无关;确实如果没有virtual也会发生同样的情况(当然,除非您通过指向Derived的指针无法调用method的{​​{1}},但会调用{而不是{1}}版本。