开发者

constness for reference class members

开发者 https://www.devze.com 2023-03-14 10:18 出处:网络
I have a couple of classes one of which keeps reference to the object of other: class Inner {}; class Outer {

I have a couple of classes one of which keeps reference to the object of other:

class Inner {};

class Outer {
    Inner & in;

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

What if I have to create Outer object from const reference to Inner? Am I have to write specific class, say OuterConst, for this?

UPD: Any neat solutions using templates? In order to avoid duplication of code in OuterConst class.

UPD2: when Inner comes without const it should be modifiable (so I can't just add const to Inner member in current imple开发者_如何学Gomentation of Outer).


What if I have to create Outer object from const reference to Inner?

Well, you can't. That's pretty much it. If Outer only needs to call const member functions of Inner, then make it a const reference- else, your class depends on a mutable Inner object and you should not create an Outer object from a const reference.


The question is whether Outer needs to modify Inner through in. If it does, you should keep in as an Inner &. In this case if you have a const Inner & then of course you can't pass it to Outer, because the reference doesn't allow you to modify the referenced Inner, but Outer does need to modify Inner.

If Outer doesn't need to modify Inner, then you should just write in as a const Inner &, in which case Outer can be initialized with either an Inner & or a const Inner &.

You can certainly write:

class Inner {};

template <class T>
class Outer {
    T& in;

public:
    Outer(T& in) : in(in) {}
};

and then initialize objects of type Outer<Inner> or Outer<const Inner>. But Outer must do something different in these two cases, as otherwise you could just make in a const Inner &. And in that case you're probably better writing separate classes, so that it's explicit that Outer does something different.


You could store a const reference, and use const_cast to cast the const away when needed. If you add some runtime checking, it's also safe.

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); }
};

And of course you can always split this into two classes: one that cannot change in, and another that can.

To do this, you could either derive the class that can change in from the class that cannot. Or you could derive both from a common base class which has the common functions as protected members, and make the appropriate ones public with using Base::Function in the derived classes.


It depends. If the two roles of Outer are different for different constness'es (one must be edited, the other not), then yes.

But if the two roles are identical (that means no changes are ever made to either a const or a non-const reference) then just always take a const Inner& as parameter. If a non-const parameter is passed it will get automatically "promoted" to a const one.

0

精彩评论

暂无评论...
验证码 换一张
取 消