我在大型合作中工作(大部分是非专业程序员,我是其中之一)。我经常看到以下
的例子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 ++术语。如何/为什么会有人争论这种做法?
答案 0 :(得分:4)
制作会员功能可以向该功能的用户显示不会修改任何班级成员。
返回的成员可能是const
也可能不是{{1}},但是使成员函数const为类的用户提供了函数行为的明确指示。
答案 1 :(得分:2)
它在很大程度上取决于设计,但对于你的情况,我不明白为什么你需要两个原型。
您需要问自己的问题是,您是否希望人们通过T
改变您的get
成员。
如果你这样做,你的原型应该如下:
T* GetMember() const {return fMember;}
如果不这样做,请返回const:
const T* GetMember() const {return fMember;}
该功能不必是const
,但可以认为它没有问题。话虽如此,你会在一个不同的非const成员函数内调用该函数吗?因为如果您打算这样做,它将无效,因为它不是const
。
由于您只返回指向成员的指针而实际上没有更改任何内容,因此我将使用函数const
。这也可以作为项目其他人的指令,该功能不会在内部修改任何内容。
返回应该是const
的选择完全取决于设计。
答案 2 :(得分:0)
我要回复说这是一个设计问题,你是否对可变访问器感到满意(在这种情况下你选择第一个const
版本),或者如果你想禁止常量引用来修改指针对象(在这种情况下,你会选择第二个,两个重载版本)。
但是考虑到这一点,我认为你的问题表明,一般来说,吸气剂和制定者都是个坏主意。你不应该盲目地转发班级成员(在这种情况下,你可能只是让他们成为公共成员)。相反,您的类应该提供一个有意义的接口来抽象实现。理想情况下,类中存在原始指针的事实永远不会引起用户的关注,并且您的接口函数负责制定相关的逻辑constness保证。
如果你选择放弃这些OO设计原则,那么我想你是独立的,你应该做最适合你整体设计的事情。
答案 3 :(得分:0)
可以说,类的逻辑结构与您对指向的内容所做的更改无关。例如,考虑一个链表节点。只要下一个(也可能是前一个)指针相同,节点就是常量,但节点并不关心是否更改下一个节点。另外,T本身可能只是设计中的不可变对象,因此const T
是无意义的区别。
答案 4 :(得分:0)
完全没问题,并且在T* const
的相同情况下很有用。
考虑从多个线程访问的哈希表。当另一个线程正在访问该对象时,内部结构不需要改变,但这并不意味着哈希表只需要包含const指针。 (锁定单个对象比锁定整个数据结构更具可伸缩性。)