这里用C ++覆盖和重载是怎么回事?

时间:2009-09-26 00:29:47

标签: c++ override overloading

这不起作用:

class Foo
{
public:
    virtual int A(int);
    virtual int A(int,int);
};
class Bar : public Foo
{
public:
    virtual int A(int);
};

Bar b;
int main()
{
    b.A(0,0);
}

似乎通过用Foo::A(int)覆盖Bar::A(int)我隐藏了Foo::A(int,int)。如果我添加一个Bar::A(int,int)的东西。

有没有人能够详细描述这里发生的事情?

5 个答案:

答案 0 :(得分:5)

本质上,名称查找在重载解析之前发生,因此派生类中的函数A会覆盖基类中的虚函数,但会隐藏任何基类中具有相同名称的所有其他函数。

可能的解决方案包括在派生类中添加using Foo::A;指令,以使派生类中可见的所有基类成员A可见,或者对具有不同签名的函数使用不同的名称。

同样请参阅here

答案 1 :(得分:2)

这里有一个讨论:http://bojolais.livejournal.com/222428.html

关键是:在C ++中,当你有一个带有重载方法的类(成员函数,你想要调用它)时,然后扩展并覆盖该方法,你必须覆盖所有重载的方法

解决方法是将呼叫更改为:

b.Foo::A(0, 0);

答案 2 :(得分:2)

// I think this kind of approach is best to avoid this kind of problems.

class Foo
{
private:
    virtual int A_impl(int);     // note the private declaration 
    virtual int A_impl(int,int); // of the actual implementation.
                                 // clients have access through the
                                 // non-virtual interface.

public:
    inline int A(int x) 
    {                            // the non virtual interface will always be visible. 
        return A_impl(x);        // and consistent.
    }
    inline int A(int x, int y) 
    {
        if (x != y) {            // also permits global parameter validation
            return A_impl(x, y); // and it's easier to set breakpoints on a
        }                        // single entry point.
        return 0;
    }
};
class Bar : public Foo
{
private:
    virtual int A_impl(int);
};

Bar b;
int main()
{
    b.A(0,0);                    // never again stuff like: ((A*)&b)->A(0,0)
}

答案 3 :(得分:0)

最简单的思考方法是记住,重载总是在单个范围内发生,而覆盖范围之间会出现重写。在确定要调用哪个函数时,编译器FIRST会查找具有该名称的最近作用域,然后解析该作用域中定义之间的重载。

答案 4 :(得分:0)

要添加上述回复,

你也可以在Bar的范围内定义重载函数,如果这是预期的结果,它总是在Foo的范围内调用相同的函数。这样可以更容易地看到代码按预期运行。