“避免返回句柄到对象内部”,所以有什么替代方法? [英] "Avoid returning handles to object internals", so what's the alternative?

查看:126
本文介绍了“避免返回句柄到对象内部”,所以有什么替代方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Scott Meyers的有效C ++ 在第5章第28项中说明了避免返回handle(指针,引用或迭代器)到对象内部,它绝对是一个好点。



不要这样做:

  class Family 
{
public:
Mother& GetMother()const;
}

因为它破坏了封装并允许更改私有对象成员。



不要这样做:

  class Family 
{
public:
const母亲& GetMother()const;
}

,因为它可能导致悬挂句柄,意味着您保留引用到已经销毁的对象的成员。



现在,我的问题是,有没有好的替代品?想象一下母亲很重!如果我现在返回母亲的副本而不是参考,GetMother正在成为一个相当昂贵的操作。



如何处理这种情况?

$ b $首先,让我重复一遍:最大的问题不是生命周期,而是封装之一。



封装不仅意味着没有人可以修改内部,如果你没有意识到,封装意味着没有人知道如何在类中实现事物,所以你可以改变类的内部,只要你



现在,不管你返回的引用是 const 还是不重要:你不小心暴露你在 Family 类中有一个 Mother 对象的事实,现在你不能摆脱它(即使你有更好的表示),因为所有的客户端可能依赖它,并且必须更改他们的代码...



最简单的解决方案是返回值:

  class Family {
public:

母亲(){return _mother; }
void mother(Mother m){_mother = m; }

private:
Mother _mother;
};因为在下一次迭代中,我可以删除 _mother 不打破界面:

  class Family {
public:

母亲){return Mother(_motherName,_motherBirthDate); }

void mother(Mother m){
_motherName = m.name();
_motherBirthDate = m.birthDate();
}

private:
名称_motherName;
BirthDate _motherBirthDate;
};

看看我如何设法完全改造内部而不改变界面一个iota?



p>显然,这种封装是以牺牲一些性能为代价的,这里有一个紧张,这是你的判断是否封装或性能应优先每次你写一个getter。


Effective C++ by Scott Meyers tells in Chapter 5, Item 28 to avoid returning "handles" (pointers, references or iterators) to object internals and it definitely makes a good point.

I.e. don't do this:

class Family
{
public:
    Mother& GetMother() const;
}

because it destroys encapsulation and allows to alter private object members.

Don't even do this:

class Family
{
public:
    const Mother& GetMother() const;
}

because it can lead to "dangling handles", meaning that you keep a reference to a member of an object that is already destroyed.

Now, my question is, are there any good alternatives? Imagine Mother is heavy! If I now return a copy of Mother instead of a reference, GetMother is becoming a rather costly operation.

How do you handle such cases?

解决方案

First, let me re-iterate: the biggest issue is not one of lifetime, but one of encapsulation.

Encapsulation does not only mean that nobody can modify an internal without you being aware of it, encapsulation means that nobody knows how things are implemented within your class, so that you can change the class internals at will as long as you keep the interface identical.

Now, whether the reference you return is const or not does not matter: you accidentally expose the fact that you have a Mother object inside of your Family class, and now you just cannot get rid of it (even if you have a better representation) because all your clients might depend on it and would have to change their code...

The simplest solution is to return by value:

class Family {
public:

    Mother mother() { return _mother; }
    void mother(Mother m) { _mother = m; }

private:
    Mother _mother;
};

Because in the next iteration I can remove _mother without breaking the interface:

class Family {
public:

     Mother mother() { return Mother(_motherName, _motherBirthDate); }

     void mother(Mother m) {
         _motherName = m.name();
         _motherBirthDate = m.birthDate();
     }

private:
     Name _motherName;
     BirthDate _motherBirthDate;
};

See how I managed to completely remodel the internals without changing the interface one iota ? Easy Peasy.

Note: obviously this transformation is for effect only...

Obviously, this encapsulation comes at the cost of some performance, there is a tension here, it's your judgement call whether encapsulation or performance should be preferred each time you write a getter.

这篇关于“避免返回句柄到对象内部”,所以有什么替代方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆