开发者

Using References in const Methods

开发者 https://www.devze.com 2023-02-13 16:00 出处:网络
Let\'s say I have a class like this: class LinkedList { struct Node { int StoredValue; // ... }; Node& GetNodeReference(std::size_t Index)

Let's say I have a class like this:

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

This won't compile because the const method Get uses GetNodeRef开发者_如何学Goerence, which cannot be const because it returns a reference.

How can I work around this?


I'm not sure what you're trying to achieve, but you could provide two overloads of GetNodeReference:

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

    return NodeReference;
}

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

    return NodeReference;
}

Note that the second overload has two const modifers, one at the beginning of the line for the return type and one at the end of the line for the implicitly passed *this object.

To avoid code repetition, you can implement the non-const overload based on the const overload:

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

This technique is discussed in Item 3 of Effective C++ by Scott Meyers.


Don't implement an indexed Get function for lists at all. It will be WAY too easy for a new developer to come in and use it in a loop, turning a linear interation into a polynomial iteration.

If you need such a capability, make a free-function that uses the builtin iterators of the list in conjunction with say std::advance to get the node you want.

If you absolutely need the member function, then the normal approach is the one suggested by @FredOverflow and use overloads (quote his code):

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


How about this?

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

};

Edit:

As you can read in the comments

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

should be changed to:

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


I suggest:

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

};

0

精彩评论

暂无评论...
验证码 换一张
取 消