What is const?

LyTning94

Dragonborn
Joined
Nov 10, 2010
Messages
397
Location
Skyrim
What exactly is the purpose of const at the end of a function? I thought I remembered reading something about it, including the fact that non-const functions cannot call const functions (or something like that).

I'm asking because of a problem I'm having calling CvUnit::plot(). I have the following code for my unit mission I added:

Code:
case MISSION_DIPLOMACY:
	if (pLoopUnit->boostDiplomacy())
	{
		bAction = true;
	}
	break;

and this code for boostDiplomacy():

Code:
bool CvUnit::boostDiplomacy()
{
	if (!canBoostDiplomacy(plot()))
	{
		return false;
	}
	
	NotifyEntity(MISSION_DIPLOMACY);

	return true;
}

canBoostDiplomacy(CvPlot* pPlot) is another function I added.

Now my mod always crashes when trying to call plot() as the parameter for canBoostDiplomacy(CvPlot* pPlot).

I looked at MISSION_ESPIONAGE and it has the exact same code, substituting espionage() for boostDiplomacy() and canEspionage(const CvPlot* pPlot) for canBoostDiplomacy(CvPlot* pPlot).

Since the game has no problem callling canEspionage(plot()), but for some reason won't call canBoostDiplomacy(plot()), I thought maybe the const highlighted above had something to do with it.

Normally I add const at the end of all my functions, since this appears to be standard. However, it wouldn't let me make boostDiplomacy() const, for some reason, because of NotifyEntity(MISSION_DIPLOMACY).

So, my question is, what exactly does const mean, and does it have anything to do with the problem I'm having? If something totally different (and probably ridiculously obvious) is causing the crash, then point it out, because I am completely baffled why this won't work.

Thanks in advance for the help!
 
Please see this thread or this thread or this thread. Const is a C++ programming concept, which is confusing, and each person learning about C++ needs to understand eventually. I am afraid that if you don't understand it, then every time you write new SDK code, you will run into this problem.
 
Thanks for the info. I turns out, though, that this isn't causing the crash, which makes me even more puzzled what is. It crashes on this code:

Code:
        DllExport int getX() const;	
#ifdef _USRDLL
	[COLOR="Gray"]inline int getX_INLINE() const
	{
		return m_iX;
	}[/COLOR]
#endif
	DllExport int getY() const;																																// Exposed to Python
#ifdef _USRDLL
	[COLOR="Gray"]inline int getY_INLINE() const
	{
		return m_iY;
	}[/COLOR]
#endif

with the code grayed out as shown. I know this is called by plot(), but don't know what calls plot() since the next item in the call stack frame is Civ4BeyondSword.exe. I tried commenting out the new code I added which calls plot() and it still crashes, so it has to be some already existing code.

I thought maybe the grayed out code was significant. I'm not sure exactly what #ifdef _USRDLL means (if defined, maybe?), but could it be returning false for some reason, making getX_INLINE() and getY_INLINE() unable to be called by plot()?
 
#ifdef is indeed 'if defined', and it's a preprecessor directive. It means that it runs as a preliminary stage of the compiler (before the actual compilation starts).

It means that if _USRDLL is not defined, the compiler completely ignores anything from there to the closing #endif directive.

Specifically in this case, this file is a header which was also used for compiling the exe.
The _USRDLL macro is only defined when compiling the DLL, but not when this header was compiled for the exe (you can look at your makefile to see where this is defined).
So the inlined function is only defined when you use this header in the DLL.
(There are many more places that are only defined for the DLL).

The reason this is grayed out is that the VS project is not aware of this macro being defined (since it is only defined in the makefile). You can define it in the project itself:
In the solution explorer right click the project item (below the solution) and choose 'properties'.
Go to 'Configuration Properties -> NMake -> Preprocessor Definitions and add _USRDLL there (the different macros should be separated with ';'). Note that it will only affect a specific configuration (debug/release).

When it crashes, what's the value of 'this'?
 
const means that the this pointer is const.

Also, objects which are const cannot call functions which are non-const. Hence member calls to non-const functions isn't allowed from a const function.

mutable members are an exception to this but that's pretty advanced stuff.
 
When it crashes, what's the value of 'this'?

In the value column:

0x00000000 {m_iID=??? m_iGroupID=??? m_iHotKeyNumber=??? ...}

I'm assuming 0x00000000 isn't actually a unit. Does this mean it's trying to call plot() on a unit that doesn't exist?
 
Yes. It's a null pointer. It's probably been deleted, or you have a dodgy cast.

EDIT: Or you could have failed to initialise a pointer in a parent object <-- most likely scenario.
 
I'm assuming 0x00000000 isn't actually a unit. Does this mean it's trying to call plot() on a unit that doesn't exist?

What you have here is a pointer to address 0, or NULL. Since this is never a valid address, it is used to mark an invalid pointer. In this case, the exe received a NULL pointer and tried calling getX (or getY) for it, so the 'this' pointer is NULL, and the member which it tries to access (m_iX) is in an inaccessible address.

Where is the code you've posted taken from? The exact same code appears in CvPlot.h, CvUnit.h and CvCity.h.

If it's CvPlot.h:
You have a NULL plot. You can get a NULL plot if you give specific illegal coordinates to (for example) CvMap::plotINLINE().

If it's CvUnit.h:
Then you somehow got a NULL unit.

Either way, if you have a specific scenario in which it happens, try placing a breakpoint on the function which returns this item (either plot or unit) and see when and why it returns NULL.
 
The code was from CvUnit.h

I used breakpoints to isolate the problem, and it seems this code is causing the crash:

Code:
NotifyEntity(MISSION_DIPLOMACY);

I commented out the code and it works fine. Does NotifyEntity() need to be included?
 
I don't really know what NotifyEntity() does. From looking at the code it seems that it has something to do with updating the unit rendering (for example when the worker surrenders to another unit) but it's pure guess.

It looks that way because it always comes after:
Code:
if (plot()->isActiveVisible(false))

But I don't know if this is otherwise important.
 
Back
Top Bottom