Вызов функции const, а не ее неконстантной версии - PullRequest
24 голосов
/ 02 сентября 2011

Я пытался обернуть что-то похожее на общие указатели данных Qt для своих целей, и после тестирования я обнаружил, что когда нужно вызывать функцию const, вместо нее была выбрана неконстантная версия.

I 'm компилируется с опциями C ++ 0x, и вот минимальный код:

struct Data {
    int x() const {
        return 1;
    }
};

template <class T>
struct container
{
    container() {
        ptr = new T();
    }


    T & operator*() {
        puts("non const data ptr");
        return *ptr;
    }

    T * operator->() {
        puts("non const data ptr");
        return ptr;
    }

    const T & operator*() const {
        puts("const data ptr");
        return *ptr;
    }

    const T * operator->() const {
        puts("const data ptr");
        return ptr;
    }

    T* ptr;
};

typedef container<Data> testType;

void testing() {
    testType test;
    test->x();
}

Как видите, Data.x является константной функцией, поэтому оператор -> вызываемый должен быть константным.И когда я закомментирую неконстантный, он компилируется без ошибок, так что это возможно.Тем не менее мой терминал печатает:

"неконстантные данные ptr"

Это ошибка GCC (у меня 4.5.2), или я что-то упускаю?

Ответы [ 4 ]

25 голосов
/ 02 сентября 2011

Если у вас есть две перегрузки, которые отличаются только по их const -ности, то компилятор разрешает вызов на основе того, является ли *this const или нет.В вашем примере кода test не является const, поэтому вызывается перегрузка не const.

Если вы сделали это:

testType test;
const testType &test2 = test;
test2->x();

, вы должны увидеть, чтовызывается другая перегрузка, потому что test2 равно const.

9 голосов
/ 02 сентября 2011

test - неконстантный объект, поэтому компилятор находит наилучшее соответствие: неконстантная версия.Вы можете применить константность с помощью static_cast, хотя: static_cast<const testType&>(test)->x();

РЕДАКТИРОВАТЬ: Кроме того, как вы подозревали в 99,9% случаев, когда вы думаете, что нашли ошибку компилятора, вы должны пересмотреть свой код, поскольку, вероятно, естькакая-то странная причуда, и компилятор фактически следует стандарту.

2 голосов
/ 02 сентября 2011

Не имеет значения, является ли Data::x постоянной функцией или нет. Вызываемый оператор принадлежит классу container<Data>, а не классу Data, и его экземпляр не является константой, поэтому вызывается непостоянный оператор. Если бы был доступен только константный оператор или экземпляр класса был бы константой сам по себе, то был бы вызван константный оператор.

0 голосов
/ 02 сентября 2011

Но testType не является константным объектом.

Таким образом, он будет вызывать неконстантную версию своих членов.
Если методы имеют абсолютно одинаковые параметры, он должен сделать выбор:версию для вызова (поэтому он использует этот параметр (скрытый)).В этом случае это не const, поэтому вы получаете неконстантный метод.

testType const test2;
test2->x();  // This will call the const version

Это не влияет на вызов x (), так как вы можете вызвать метод const для неконстантного объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...