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.
精彩评论