开发者

Why am I disallowed from calling methods on an object I've returned by const reference?

This is a follow up question to my earlier question concerning returning references in C++: Best way to return an object in c++?

I can successfully return a reference, however, I am unable to prevent an observer to completely overwrite the variable in question. I have used const references, but I want an observer to be able to alter values.

Code below:

class Layer {
public:
    Channel&        getChannel();
private:
    Channel         channel;
};

// return reference to channel
Channel& Layer::getChannel() {
    return channel;
};

// FINE
layer.getChannel().someMethod();

// BAD: PRIVATE MEMBER IS OVERWRITTEN
layer.getChannel() = Channel();

Now I'm pretty sure to prevent this I have to alter the signature of the function to return a const reference, however, I'm unable to call someMethod afterwards:

// CHANGE TO CONST REFERENCE
Channel const& Layer::getChannel() {
    return channel;
};

// return const ref of channel
Channel const& channel = layer.getChannel();

// ERR开发者_如何学GoOR!!
// 'Channel::someMethod' : cannot convert 'this' pointer from 'const Channel' to 'Channel &'
channel.someMethod();

What's the correct way to write this — and is there a way to prevent overwriting of a private variable?


Mark all methods that should be callable on const objects as const:

class Layer
{
    // ...

public:

    void someMethod() const;
};

void Layer::someMethod() const
{
    // ...
}

Note that you cannot mutate the object inside a const method, except for data members declared as mutable (which are quite rare; lazily initialized hash values come to mind).

If you want to prevent assignments, simply declare the assignment operator as private:

class Layer
{
    // ...

private:

    Layer& operator=(const Layer&);
};


If the object is private, users of the class should not know the object exists, or at least they should not need to know. You need to write public functions that perform the operations that you want the user to be able to perform.

So, instead of this:

layer.getChannel().someMethod();

You should have this:

layer.someOtherMethod();

Which calls a function that might look something like this:

X Layer::someOtherMethod()
{
    return channel.someMethod();
}


[I agree with some of the other redesign solutions, but to answer the specific question]

If you want to return a mutable object but disallow assignment, make a private copy constructor and assignment operator on Channel. If you still need channel = ... elsewhere (which you may not if you use another explicit constructor in Layer) you can make Layer a friend.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜