Question

Please definitively explain what the method resolution rules are in the following case. I have an idea, based on the behavior of the code, but would like clarification.

Based on "The const-ness of the calling object determines which version of MyArray::Get() will be invoked and thus whether or not the caller is given a reference with which he can manipulate or only observe the private data in the object. The two methods technically have different signatures because their "this" pointers have different types, allowing the compiler to choose the right one" from wikipedia const correctness, I would conclude that my example should be a case of method overloading, not method overriding (since a const method and a non-const method have two different signatures).

class Base
{
public:

    void test()
    { std::cout << "nonconst call" << std::endl; }
};

class Child : public Base
{
public:

    void test() const
    {
        std::cout << "const call" << std::endl;
        Child * nonConstThis = const_cast<Child * >(this);
        Base * nonConstBase = dynamic_cast<Base * >(nonConstThis);

        // This call leads to infinite recursion by calling
        // "void Child::test() const", which implies that
        // a "Child *" will resolve to calling a const Child function
        // before calling a non-const Base function.
        //nonConstThis->test();

        // This will call "void Base::test()"
        nonConstBase->test();
    }

};

void main()
{
    Child * child = new Child;
    child->test();
}
Was it helpful?

Solution

It's actually method hiding, not overloading.

When you create a method with the same name in a derived class, the base class version is no longer visible.

struct A
{
    void foo() {}
};

struct B : public A
{
    void foo(int x) {}
};

B b;
b.foo(); //error

I'm assuming you expect B::foo() to exist, but, as you can see, it does not. So nothing, not cv-qualifiers (const) or parameters affect this.

In your case the name isn't resolved because it has something to do with the const, but because you're calling test on an object of type Child. You then call Base::test() on an object of type Base, just like the following would work form my example:

((A)b).foo();

OTHER TIPS

You are stumbling on how overload name resolution works in C++. The function "test" in the base class becomes "hidden" (it's called name hiding). When looking for a suitable function to call, the compiler looks in the derived class first, sees a match, then stops looking. This answer has a good description as to why.

You can use a using declaration to look in the base class as well like this:

class Child : public Base
{
public:
    using Base::test;

this will tell the compiler to also look in Base for test.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top