I would like to have a class which allows access to the const interface of it's base case, but not otherwise. In particular:
class B
{};
class A : private class B
{
public:
operator const B&() { return *this; }
};
int main()
{
A a;
const B& b = a; // Should this line be an error?
}
g++ gives an inaccessible base class error. Do you language experts out there think that this error is correct in C++11/C++14?
And yes, I realize I can (and will) just do this:
int main()
{
A a;
const B& b = a.operator const B&();
}
Any suggestions on another method for this construct?
You cannot overload an operator working on fundamental types. That is, you can't overload the '+' operator for two int s (fundamental type) to perform subtraction. You cannot change the syntax rules (such as associativity, precedence and number of arguments) of the overloaded operator.
For numbers beginning with 616: dial 011-81-176-66-xxxx. For numbers beginning with 226: dial 011-81-176-77-xxxx. To call the base operator, dial 011-81-176-53-5181.
Since you do not have access to the stream object (its not yours to modify) these can not be member operators they have to be external to the class. Thus they must either be friends of the class or have access to a public method that will do the streaming for you.
The const qualifier ensures that the parameter (param) is not altered inside the operator=() method. The above method alters the right hand side operand 'param' after assigning the value to the left hand side operand. The const qualifier helps you not to violate the semantics of the assignment operation.
[dcl.init.ref]/5:
A reference to type “cv1
T1
” is initialized by an expression of type “cv2T2
” as follows:
If the reference is an lvalue reference and the initializer expression
- is an lvalue (but is not a bit-field), and “cv1
T1
” is reference-compatible with “cv2T2
,” or- has a class type (i.e.,
T2
is a class type), whereT1
is not reference-related toT2
, [..]then the reference is bound to the initializer expression lvalue in the first case and to the lvalue result of the conversion in the second case (or, in either case, to the appropriate base class subobject of the object).
The conversion function would be covered in the second bullet point. However, B
is reference-related to (and -compatible with) A
even though it's a private base class, so the first bullet point applies. Now [dcl.init.ref]/4 defines this scenario to be ill-formed:
Given types “cv1
T1
” and “cv1T2
”, “cv1T1
” is reference-related to “cv1T2
” ifT1
is the same type asT2
, orT1
is a base class ofT2
. “cv1T1
” is reference-compatible with “cv2T2
” ifT1
is reference-related toT2
and cv1 is the same cv-qualification as, or greater cv-qualification than, cv2. In all cases where the reference-related or reference-compatible relationship of two types is used to establish the validity of a reference binding, andT1
is a base class ofT2
, a program that necessitates such a binding is ill-formed ifT1
is an inaccessible [..] base class ofT2
.
Such reference bindings will thus always fail, regardless of any conversion functions available. Reference binding cannot work with private inheritance.
Your explicit call is the solution of this problem, though there is no need for a conversion operator anymore: Simply define a getter that returns a const
-reference. E.g.
const B& b = a.getB();
const B& b = a;
doesn't invoke A::operator const B&()
. This behavior exists since C++03 days.
It's a simple upcasting which happens from a derived type to a base type. This upcasting throws compiler error because the base (class B
) is privately inherited by the derived (class A
) in a global scope.
Had there been no such inheritance relationship between B
and A
, then definitely the mentioned operator const B&()
would have been instantiated as per your expectation.
The error is correct. An implicit conversion (in this case, via your operator) is only considered if the types are not reference-related. The inheritance relationship means they are, so the reference would bind directly without conversion, but that fails due to the private inheritance.
Unless you have a good reason for inheritance, you might make the A
a member rather than a base class. In that case, a conversion operator returning a reference to that member would do what you want.
If you do need the inheritance, then a suitably named function might be nicer than requiring an explicit operator call.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With