Использование ссылок в методах const - PullRequest
2 голосов
/ 25 февраля 2011

Допустим, у меня есть такой класс:

class LinkedList
{
    struct Node
    {
        int StoredValue;
        // ...
    };

    Node& GetNodeReference(std::size_t Index)
    {
        // ...

        return NodeReference;
    }

    public:

    int Get(std::size_t Index) const
    {
        return GetNodeReference(Index).StoredValue;
    }
};

Это не скомпилируется, потому что метод const Get использует GetNodeReference, который не может быть const, потому что он возвращает ссылку.

Как я могу обойти это?

Ответы [ 4 ]

8 голосов
/ 25 февраля 2011

Я не уверен, что вы пытаетесь достичь, но вы могли бы обеспечить две перегрузки GetNodeReference:

Node& GetNodeReference(std::size_t Index)
{
    // ...

    return NodeReference;
}

const Node& GetNodeReference(std::size_t Index) const
{
    // ...

    return NodeReference;
}

Обратите внимание, что вторая перегрузка имеет два модификатора const, один в начале строки для возвращаемого типа и один в конце строки для неявно переданного *this объекта.

Чтобы избежать повторения кода, вы можете реализовать неконстантную перегрузку на основе константной перегрузки:

const Node& GetNodeReference(std::size_t Index) const
{
    // ...

    return NodeReference;
}

Node& GetNodeReference(std::size_t Index)
{
    return const_cast<Node&>(static_cast<const LinkedList&>(*this).getNodeReference(Index));
}

Эта техника обсуждается в пункте 3 Эффективный C ++ Скоттом Мейерсом.

3 голосов
/ 25 февраля 2011

Не реализовывать индексированную функцию Get для списков вообще. Это будет слишком легко для нового разработчика, чтобы войти и использовать его в цикле, превращая линейное целое в полиномиальную итерацию.

Если вам нужна такая возможность, создайте свободную функцию, которая использует встроенные итераторы списка вместе с скажем std::advance, чтобы получить нужный вам узел.

Если вам абсолютно необходима функция-член, то нормальный подход - тот, который предложен @FredOverflow, и используйте перегрузки (процитируйте его код):

const Node& GetNodeReference(std::size_t Index) const
{
    // ...

    return NodeReference;
}

Node& GetNodeReference(std::size_t Index)
{
    return const_cast<Node&>(static_cast<const LinkedList&>(*this).getNodeReference(Index));
}
1 голос
/ 25 февраля 2011

Как насчет этого?

class LinkedList {

private:

struct Node
{
    int StoredValue;
    // ...
};

Node NodeReference;

const Node* const GetNodeReference(std::size_t Index) const
{
    return &NodeReference;
}

public:

int Get(std::size_t Index) const
{
    const Node *const node = GetNodeReference(Index);
    return node->StoredValue;
}

};

Редактировать:

Как вы можете прочитать в комментариях

const Node * const GetNodeReference (std :: size_t Index)const () ...

должен быть изменен на:

const Node * GetNodeReference (std :: size_t Index) const () ...

0 голосов
/ 25 февраля 2011

Я предлагаю:

class LinkedList {

private:

struct Node
{
    int StoredValue;
    // ...
};

Node NodeReference;

const Node& GetNodeReference(std::size_t Index) const
{
    return NodeReference;
}

public:

int Get(std::size_t Index) const
{
    const Node node = GetNodeReference(Index);
    return node.StoredValue;
}

};

...