参考类成员的恒定性

constness for reference class members

本文关键字:恒定性 成员 参考      更新时间:2023-10-16

我有几个类,其中一个类保留对另一个对象的引用:

class Inner {};
class Outer {
    Inner & in;
public:
    Outer(Inner & in) : in(in) {}
};

如果我必须从常量引用到 Inner 创建外部对象怎么办?我必须为此编写特定的类,比如说 OuterConst?

UPD:使用模板有什么简洁的解决方案吗?为了避免 OuterConst 类中的代码重复。

UPD2:当 Inner 没有 const 时,它应该是可修改的(所以我不能在当前的 Outer 实现中将 const 添加到 Inner 成员中(。

如果我必须从常量引用到 Inner 创建外部对象怎么办?

好吧,你不能。差不多就是这样。如果 Outer 只需要调用 Inner 的 const 成员函数,那么使其成为 const 引用 - 否则,您的类依赖于可变的 Inner 对象,您不应该从 const 引用创建 Outer 对象。

问题是Outer是否需要通过in修改Inner。如果是这样,您应该保留in作为Inner &。在这种情况下,如果你有一个const Inner &那么当然你不能把它传递给Outer,因为引用不允许你修改引用的Inner,但Outer确实需要修改Inner

如果Outer不需要修改Inner,那么你应该只in写成const Inner &,在这种情况下,Outer可以用Inner &const Inner &初始化。

你当然可以写:

class Inner {};
template <class T>
class Outer {
    T& in;
public:
    Outer(T& in) : in(in) {}
};

然后初始化类型为 Outer<Inner>Outer<const Inner> 的对象。但是Outer必须在这两种情况下做一些不同的事情,否则你可以in const Inner & .在这种情况下,您可能最好编写单独的类,以便明确Outer执行不同操作。

您可以存储常量引用,并在需要时使用 const_cast 将常量丢弃。如果添加一些运行时检查,它也是安全的。

class Inner { /* ... */ };
class Outer {
    Inner const & in;
    bool const inIsConst;
    Inner & inMutable()
    {
        if (inIsConst)
            throw std::logic_error("in is const.");
        else
            return const_cast<Inner &>(in);
    }
public:
    Outer(Inner const & in) : in(in), inIsConst(true) {}
    Outer(Inner & in) : in(in), inIsConst(false) {}
    // always safe
    void Foo() { std::cout << in.getFoo(); }
    // will throw if *this was constructed with a const Inner
    void Bar() { inMutable().setFoo(in.getFoo() + 1); }
};

当然,您始终可以将其分为两类:一类不能更改in,另一类可以。

为此,您可以从不能更改的类派生可以更改in的类。或者,您可以从具有作为受保护成员的公共函数的公共基类派生两者,并使用派生类中的using Base::Function公开适当的基类。

这取决于。如果Outer的两个角色对于不同的常性是不同的(一个必须编辑,另一个不编辑(,那么是的。

但是,如果这两个角色相同(这意味着不会对常量或非常量引用进行任何更改(,则始终将const Inner&作为参数。如果传递了一个非常量参数,它将自动"提升"为const参数。