代码中的缺陷:即使使用const
类型限定符管理对const
类型的成员函数的访问以及对其成员的访问。由于您的成员B & b
是参考,const
因此在这里对您没有多大作用:无论哪种方式,在初始化后都无法更改参考。甚至没有考虑如何访问该引用的目标:
const A a(b);
a.b.non_const_function(); // OOPS, no problem!
带模板的解决方案
您可以向您的类型添加一个“标志”,而不是(ab)使用const
类型限定符,以区分您需要能够进行非常量访问的情况和您没有的情况:
#include <type_traits>
struct B {
void danger() {
}
void all_fine() const {
}
};
template<bool Writeable>
struct A {
using BRef = typename std::conditional<Writeable, B &, B const &>::type;
BRef b;
A (BRef b) : b(b) {};
};
using ConstA = A<false>;
using NonConstA = A<true>;
int main() {
B b;
ConstA a(b);
//NonConstA nc_a(a);
ConstA another_a(a);
//another_a.b.danger();
another_a.b.all_fine();
NonConstA a2(b);
a2.b.danger();
}
对于某些功能,您可以根据它们是否需要“可写”std::enable_if
来选择性地启用/禁用成员函数。A
b
真正的解决方案:重构你的设计
但我想更加强调这条评论:
“有时 b 必须是只读的,有时它是可写的。” 你所有的问题都源于这种奇怪的二元性。我建议为您的班级选择一组语义,而不是两个
来自轨道上的轻盈竞赛
您可能应该考虑拆分您的类,以便您拥有 a和 aCommonA
都使用的功能(名称很糟糕,但我希望您理解我的意思)。WriteableA
NonWriteableA