There are two areas you could go, more OOP or more Functional . One of them implies less concern for the manipulation of the state, but rather about the behavior, the other completely forgets about the behavior and cares about the returned state.
Oop
For me, the key principle of OOP is Tell, Don't Ask or write no getters or setters .
Create your objects so that they say what to do in order to be autonomous. Do not ask him to return some object that you can then use to do something. Just say to do what you want in the first place. If you tell the object to do something, you probably expect it to change state, and it is not that it was const .
Your SpecialClass may provide some doService() . Instead, you can specify a Class in doSpecialService() , which is correctly modified.
An alternative is to create this object to use some other object to create. Thus, the function can be const, but take no const parameter:
class Class { public: void doService(ServiceProvider& serviceProvider) const { serviceProvider.doService(x, y); } };
With this, you will go to SpecialServiceProvider& , which would create the correct SpecialClass for the X and Y data. That would be volatile. It would be correct to change the state when providing the service. Perhaps you could cache a map of SpecialClass objects for pairs ( X , Y ).
Functional
Another direction is to make your objects immutable. Whenever you want a new state to create it, using the old state as the basis. This can cause a hit until you have turtles (almost) to the end:
class SpecialBuilder { public: SpecialBuilder withX(const X& newX) const; SpecialBuilder withY(const Y& newY) const; SpecialClass build() const; }; SpecialBuilder specialBuilder; SpecialClass special = specialBuilder.withX(x).withY(y).build();
You can exchange data between each returned SpecialBuilder , as it is immutable.