Как разрешается мой вызов метода? - PullRequest
1 голос
/ 13 марта 2012

Пожалуйста, окончательно объясните, каковы правила разрешения метода в следующем случае.У меня есть идея, основанная на поведении кода, но хотелось бы пояснения.

На основе "Константность вызывающего объекта определяет, какая версия MyArray :: Get () будет вызвана и, таким образом,дается ли вызывающей стороне ссылка, с помощью которой он может манипулировать или наблюдать только личные данные в объекте. Технически два метода имеют разные сигнатуры, потому что их указатели «this» имеют разные типы, что позволяет компилятору выбирать правильный »из википедии const правильности , я бы пришел к выводу, что мой пример должен быть случай перегрузка метода, не переопределение метода (так как метод const и неконстантныйметод имеет две разные подписи).

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();
}

Ответы [ 2 ]

3 голосов
/ 13 марта 2012

Вы спотыкаетесь о том, как работает разрешение имен перегрузки в C ++.Функция «тест» в базовом классе становится «скрытой» (это называется скрытием имени).При поиске подходящей функции для вызова компилятор сначала ищет в производном классе, видит совпадение, а затем прекращает поиск. Этот ответ имеет хорошее описание того, почему .

Вы можете использовать объявление using для просмотра базового класса, а также так:

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

это будетскажите компилятору также посмотреть в базе для проверки.

3 голосов
/ 13 марта 2012

Это на самом деле метод сокрытия, а не перегрузки.

Когда вы создаете метод с тем же именем в производном классе, версия базового класса больше не отображается.

struct A
{
    void foo() {}
};

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

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

Я предполагаю, что вы ожидаете, что B::foo() существует, но, как вы можете видеть, это не так. Так что ничто, ни cv-квалификаторы (const), ни параметры не влияют на это.

В вашем случае имя не разрешено, потому что оно имеет отношение к const, а потому что вы вызываете test для объекта типа Child. Затем вы вызываете Base::test() для объекта типа Base, как в следующем примере будет работать следующее:

((A)b).foo();
...