一个const成员函数,返回一个指向非const成员变量的指针,为什么它是好的

a const member function, returning a pointer to a non const member variable, why would it be good?

本文关键字:一个 成员 const 变量 指针 为什么 返回 函数      更新时间:2023-10-16

我在一个大型团队中工作(大多数是非专业程序员,我是其中之一)。我经常看到下面的例子

void T::DoChanges(I i); // will make changes to internal structure of T (non-const)
V T::GetValue();
class A
{
private:
  T* fMember;
public:
  A(); 
  T* GetMember() const {return fMember;}
}

,其中用例将是

A a;
I i;
a->GetMember()->DoChanges(i);
V v = a->GetMember()->GetValue();

这种做法违反了我在学习编程课程时学到的一个原则,即const不仅指类实例的位结构,还指内部逻辑结构。在这种理念下,成员函数应该采用以下形式:

T* GetMember() {return fMember;}
const T* GetMember() const {return fMember;}

我听说有些人认为const应该只引用成员,严格地用c++术语来说。为什么有人会赞成这种做法?

创建成员函数向该函数的用户表明,它不会修改任何类成员。
返回的成员可以是也可以不是const,但是将成员函数设置为const可以让类的用户清楚地知道函数的行为。

这在很大程度上取决于设计,但对于您的情况,我不明白为什么需要两个原型。

你需要问自己的问题是,你是否希望人们通过get来改变你的T成员。

如果你这样做了,你的原型应该是这样的:

T* GetMember() const {return fMember;}

如果没有,则将返回值设为const:

const T* GetMember() const {return fMember;}

函数不一定是const,但考虑到它可以没有问题。话虽如此,您会在不同的非const成员函数中调用该函数吗?因为如果你打算这样做,它不会工作,因为它不是const

因为你只返回一个指向成员的指针,而实际上没有改变任何东西,我将使函数const。这也可以作为一个指示,指示其他在项目上工作的人,该函数不会在内部修改任何东西。

返回值是否应该是const完全取决于设计。

我要回答说,这是一个设计问题,你是否喜欢可变访问器(在这种情况下,你选择第一个const版本),或者如果你想禁止常数引用来修改指针(在这种情况下,你选择第二个,两个重载版本)。

但是仔细想想,我认为你的问题表明getter和setter通常是一个坏主意。您不应该盲目地转发类成员(在这种情况下,您不妨将它们设置为公共成员)。相反,您的类应该提供一个抽象实现的有意义的接口。因此,理想情况下,在你的类中有一个原始指针这一事实永远不应该引起用户的关注,而你的接口函数会负责做出相关的逻辑一致性保证。

如果您选择放弃这些OO设计原则,那么我认为您只能靠自己了,您应该做最适合您整体设计的任何事情。

可以说,类的逻辑结构与您对所指向的内容所做的更改无关。例如,考虑一个链表节点。只要下一个(也可能是前一个)指针相同,节点就是常量——但是节点并不关心您是否更改了下一个节点。此外,T本身在设计上可能只是一个不可变对象,因此const T是一个没有意义的区别。

这非常好,并且在与T* const相同的情况下非常有用。

考虑从多个线程访问哈希表。当另一个线程访问对象时,内部结构不需要改变,但这并不意味着哈希表只需要包含const指针。(锁定单个对象比锁定整个数据结构更具可扩展性。)