newbie C++ question, why are const functions in OpenMW sometimes used to change values?

Everything about development and the OpenMW source code.
Post Reply
mattwla
Posts: 59
Joined: 17 Jul 2017, 14:45

newbie C++ question, why are const functions in OpenMW sometimes used to change values?

Post by mattwla »

Hi, new C++ programmer here, poking around OpenMW to get a feel for the language.

In my C++ tutorials I've learned you can make a function a const function if you don't want it to change any values.

But, unless I am mistaken, const functions in OpenMW are used to change values, such as
void Npc::onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, const osg::Vec3f &hitPosition, bool successful) const
Here we have the NPC onHit function, which happens when an NPC gets hit... and it causes the NPC's health to drain. But... it is const? I am confused, this const function is causing a value change? How? Why?

Thanks so much!
Chris
Posts: 1626
Joined: 04 Sep 2011, 08:33

Re: newbie C++ question, why are const functions in OpenMW sometimes used to change values?

Post by Chris »

For C++ class methods, 'const' means you won't modify any class member variables. It's completely valid to change other memory that's separate from the class. For C++ class methods, it's sometimes easier to consider them as having an implicit 'this' pointer parameter. And qualifiers such as const (or volatile), are applied to what 'this' points to. So for example, with

Code: Select all

class Npc {
    ...
    void onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, const osg::Vec3f &hitPosition, bool successful) const;
    ...
};
you can think of it like

Code: Select all

void onHit(const Npc *this, const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, const osg::Vec3f &hitPosition, bool successful);
};
whereas if the const qualifier was omitted, it would be like

Code: Select all

void onHit(Npc *this, const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, const osg::Vec3f &hitPosition, bool successful);
};
More conceptually, as I understand it, OpenMW doesn't store the NPC state in the Npc class. Instead, the NPC state is divided into sub-groups. So for instance, NPCs have 'actor-specific state' (position, name, etc), 'creature-specific state' (health, AI, etc), and 'npc-specific state' (skills, attributes, etc). This is because different actor types are comprised of different sub-groups of state, and it's helpful to keep each sharable sub-group type together for common access, rather than duplicating it for each type (e.g. no need to define NPCs and Monsters as completely separately object types, when they have common state like names, positions, health, AI, etc).

In this case, the Npc class simply provides access to get, use, or modify state an NPC would have, which is stored elsewhere. Because an NPC being hit needs to check npc-specific state (skills and attributes), an NPC being hit would need to call Npc::onHit. The MWWorld::Ptr object acts as a lookup for the Npc class to know which instance's state to use. And because an NPC also has actor- and creature-specific state, the same Ptr can be used to get, use, or modify actor- and creature-specific state too, since they all belong to the same object instance.
mattwla
Posts: 59
Joined: 17 Jul 2017, 14:45

Re: newbie C++ question, why are const functions in OpenMW sometimes used to change values?

Post by mattwla »

Chris, thanks a lot for your explanation, I hope you don't mind if I ask some follow up questions.

So, to make sure I'm understanding properly: In the onHit example, making the onHit member function const makes it so no changes can happen to the class the member function belongs to (in this case the npc class), but changes can happen to other classes through the function. npc class data couldn't be changed, but other classes of data that belong to the NPC could (such as creature stats or actor stuff).

Is there a reason it is done this way? if someone wanted to effect the NPC's npc class data when they were hit, would they have to do it without using onHit? I'm not planning on doing anything like that, I'm just curious to test my understanding.
Chris
Posts: 1626
Joined: 04 Sep 2011, 08:33

Re: newbie C++ question, why are const functions in OpenMW sometimes used to change values?

Post by Chris »

mattwla wrote: 25 Jul 2017, 02:26 So, to make sure I'm understanding properly: In the onHit example, making the onHit member function const makes it so no changes can happen to the class the member function belongs to (in this case the npc class), but changes can happen to other classes through the function. npc class data couldn't be changed, but other classes of data that belong to the NPC could (such as creature stats or actor stuff).
Yes and no. With the 'const' qualifier, the method can't alter member variables in the Npc class. However, the Npc class is just an interface for handling things related to NPCs (or things which "derive" from NPCs), and doesn't directly store NPC-related data. So the onHit method being const doesn't mean npc-related state can't be modified, because that state isn't stored directly in the Npc class.
Post Reply