Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Implicit Conversion Operators

I'm trying to find a nice inheritance solution in C++.

I have a Rectangle class and a Square class. The Square class can't publicly inherit from Rectangle, because it cannot completely fulfill the rectangle's requirements. For example, a Rectangle can have it's width and height each set separately, and this of course is impossible with a Square.

So, my dilemma. Square obviously will share a lot of code with Rectangle; they are quite similar.

For examlpe, if I have a function like:

bool IsPointInRectangle(const Rectangle& rect);

it should work for a square too. In fact, I have a ton of such functions.

So in making my Square class, I figured I would use private inheritance with a publicly accessible Rectangle conversion operator. So my square class looks like:

class Square : private Rectangle
{
    public:
        operator const Rectangle&() const;
};

However, when I try to pass a Square to the IsPointInRectangle function, my compiler just complains that "Rectangle is an inaccessible base" in that context. I expect it to notice the Rectangle operator and use that instead.

Is what I'm trying to do even possible?

If this can't work I'm probably going to refactor part of Rectangle into MutableRectangle class.

Thanks.

like image 477
Imbue Avatar asked Mar 20 '10 15:03

Imbue


People also ask

Does C have implicit type conversion?

Overview. Implicit type conversion in C language is the conversion of one data type into another datatype by the compiler during the execution of the program. It is also called automatic type conversion.

Does C have implicit casting?

Implicit type conversion in C happens automatically when a value is copied to its compatible data type. During conversion, strict rules for type conversion are applied. If the operands are of two different data types, then an operand having lower data type is automatically converted into a higher data type.

Does C++ have implicit conversion?

An implicit conversion sequence is the sequence of conversions required to convert an argument in a function call to the type of the corresponding parameter in a function declaration. The compiler tries to determine an implicit conversion sequence for each argument.

What is C++ conversion operator?

Conversion Operators in C++ C++ supports object oriented design. So we can create classes of some real world objects as concrete types. Sometimes we need to convert some concrete type objects to some other type objects or some primitive datatypes. To make this conversion we can use conversion operator.


2 Answers

You can make a class ImmutableRectangle, without any mutators and with only const methods, from which you can correctly derive both Rectangle, and, separately, ImmutableSquare and, from that, Square. Note that, shorn of mutability, the IS-A relationship does hold -- an immutable square IS-A immutable rectangle: mutability is the only serious issue, so by factoring it out you can get some substantial code reuse (for all const uses -- ones that don't in fact use, or need, mutability).

Introducing mutability along the inheritance is OK as long as no class invariants of the (immutable) base actually rely on the immutability characteristic; and of course an immutable object can be properly constructed from a const pointer or reference to the mutable version (presumably in a separate inline friend function to avoid giving the base class a dependency on the derived class;-) for reasonably-handy use.

Edit: one comment understandably expresses qualms because "a mutabe is not an immutable": to reason about this, you need to understand what "IS-A" means... and it does not mean the Korzybski-denied "is of identity": it means the LSP. Go through the rigmarole of constraints this means: covariance, contravariance, weaker-equal preconditions, stronger-equal postconditions, etc, as they apply to the const methods of the base (immutable) and derived (mutable) classes. You'll see that class invariants are the only issue, as I mentioned in the previous paragraph, so just avoid asserting immutability as a class invariant and you're in clover;-).

Maybe it would help to name the base class NotNecessarilyMutableRectangle since it doesn't assert immutability as a class invariant; that very precise naming might be philosophically reassuring but perhaps a trifle un-handy in everyday coding.

like image 140
Alex Martelli Avatar answered Sep 21 '22 00:09

Alex Martelli


Well, I'm surprised. It seems privately inheriting a class A prevents you from using operator A outside the class.

You can solve your problem by making a member Rectangle for square and using it for the cast:

class Square {
    Rectangle r;
    public:
        operator const Rectangle&() const {
            return r;
        }
};

This should compile and work. And I believe it won't give you that much more work to do if any.

like image 38
Shiroko Avatar answered Sep 18 '22 00:09

Shiroko