hexcoffee hexcoffee - 2 months ago 6
C++ Question

Correct OOP-design, if I want to call non-const function of const reference?

I guess I still have to learn a lot about not only C++, but object oriented programming itself. In a recent C++-project, I came across one question quite frecuently: If I have a situation where I want to pass a const reference to some object, how can I use non-const functions of that object?

Let me give an example: Say I have a class with some data and a function with a small calculation with that data, for instance



class Person
{
private:
float weight;
float height;
float age;
...

public:
float bodyMassIndex();
};


Now I have another class with different expertise, e.g.

class GymInstructor
{
private:
float knowledge;
int age;
...

public:
int recommendDumbbellWeight(const Person &person);
};


Now say the function
GymInstructor::recommendDumbbellWeight
wants to use the function
Person::bodyMassIndex()
in its calculation.

Here is the list of things I should avoid or cannot do:

+ Making a local copy of the
Person
inside
recommendDumbbellWeight
(so avoid something like
GymInstructor::recommendDumbbellWeight(Person person)
) because I do not need to and it slows down my program

+ Giving a pointer to
recommendDumbbellWeight
by something like
GymInstructor::recommendDumbbellWeight(Person *pPerson)
, because I just nead read-only access and should therefore avoid any errors by giving write-access to
recommendDumbbellWeight


+ Make Person::bodyMassIndex a
const
function, because it depends on the state of the object, here e.g.
weight
and
height
.

+ Moving the function
bodyMassIndex()
to some other class, because it uses the data of the
Person
, so there is no real reason why another object should perform that calculation. If so, I would have to pass all the data to that other class.

+ Say,
GymInstructor::recommendDumbbellWeight
needs a lot more results of small calculations like
Person::bodyMassIndex()
, then I also should avoid just passing the result of the calculation with something like
GymInstructor::recommendDumbbellWeight(float bodyMassIndex, float experience, float fitness, ...
because it blows up my parameter list which looks ugly and produces unnecessary code.

So what is actually left? I would love to call
Person::bodyMassIndex()
in
GymInstructor::recommendDumbbellWeight(const Person &person)
, but I can't, because
person
is a const reference.

I assume that either I am too stupid to see the very obvious solution or there is something fundamentally wrong in my design. How would I solve my problem?

Answer

Declaring a method const is somewhat like making a promise that it won't try to modify the object. It will not deny you access to the object state and you still will be perfectly able to call it for non-const objects. So yes, the solution is float bodyMassIndex() const;