Подтвердить что ты не робот

Вызов функции const, а не ее неконстантной версии

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

Я компилирую с параметрами С++ 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 является функцией const, поэтому вызываемый оператор → должен быть const. И когда я комментирую неконстантный, он компилируется без ошибок, поэтому это возможно. Тем не менее мой терминал печатает:

"non const data ptr"

Является ли это ошибкой GCC (у меня есть 4.5.2), или что-то мне не хватает?

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

Ответ 3

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

Ответ 4

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

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

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

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