C ++ чисто виртуальные методы - PullRequest
5 голосов
/ 04 июня 2011

Рассмотрим эту демонстрационную программу:

#include <stdio.h>

class Base
{
public:
    virtual int f(int) =0;
    virtual int f(){ return f(0); }

    virtual ~Base(){ }
};

class Derived : public Base
{
public:
    int f(int i)
    {
        return (10 + i);
    }
};

int main(void)
{
    Derived obj;
    printf("%d\n", obj.f(1));  // This works, and returns 11
    printf("%d\n", obj.f());   // Adding this line gives me the error listed below
}

, которая дает мне следующую ошибку компиляции:

virtualfunc.cpp: In function ‘int main()’:
virtualfunc.cpp:25:26: error: no matching function for call to ‘Derived::f()’
virtualfunc.cpp:15:9: note: candidate is: virtual int Derived::f(int)

Я надеялся, что вызов obj.f() приведет к вызовуBase::obj.f(), поскольку производный класс не определяет его, что приведет к вызову Derived::obj.f(0) для определения в классе Base.

Что я здесь не так делаю?Есть ли способ сделать это?В частности, я бы хотел, чтобы вызов obj.f() возвратил 10.

(Также обратите внимание, что я понимаю, что мог бы использовать аргумент по умолчанию для решения этой проблемы, но этот код является просто кратким примером моей проблемыПоэтому, пожалуйста, не говорите мне использовать аргументы по умолчанию.)

Спасибо.

Ответы [ 3 ]

8 голосов
/ 04 июня 2011

Проблема, с которой вы сталкиваетесь, ортогональна чисто виртуальным функциям и связана с тем, как C ++ выполняет разрешение имен в иерархиях классов.

Когда вы пишете

obj.f();

C ++ пытаетсяискать функцию с именем f, чтобы она знала, что вызывать.Поскольку obj имеет тип Derived, он начинается внутри Derived и ищет функцию с именем f.В итоге он находит Derived::f(int), и хотя эта функция принимает аргумент, C ++ считает, что это метод, который вы пытаетесь вызвать, и поэтому перестает искать.Затем компилятор замечает, что вы пытаетесь вызвать его без параметров, и выдает ошибку о вызове функции.

Чтобы это исправить, вы должны сообщить компилятору C ++, что он также должен попытаться найтифункция Base::f(), которая содержится в базовом классе.Для этого вы можете изменить определение Derived следующим образом:

class Derived : public Base
{
public:
    int f(int i)
    {
        return (10 + i);
    }

    using Base::f;
};

Эта строка using Base::f говорит C ++, что она должна обрабатывать функции в Base с именем f, как будто они являются частьюDerived.Таким образом, когда компилятор пытается найти функцию с именем f, он находит и Derived::f(int), и Base::f().Вызов тогда будет успешным, потому что компилятор может выяснить, что вы пытаетесь вызвать Base::f() с кодом, который вы перечислили.

Надеюсь, это поможет!

3 голосов
/ 04 июня 2011

Причина в том, что определенные fDerived) hides функции f из класса Base. Решение состоит в том, чтобы добавить using. Как это:

class Derived : public Base
{
public:
    int f(int i)
    {
        return (10 + i);
    }

//  vvvvvvvvvvvvvv
    using Base::f;
};
3 голосов
/ 04 июня 2011

Определение f(int) в производном классе скрывает имя Base::f, которое вы не переопределили. Все, что вам нужно сделать, это показать это, написав using Base::f; в производном классе:

class Derived : public Base
{
public:

    using Base::f;   //note this line!

    int f(int i)
    {
        return (10 + i);
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...