Cleaning and 'improving' your code (const)

Started by
18 comments, last by cozzie 10 years, 9 months ago

Thanks. I understand what you mean with 'blind staring' on style (and possible OCD :))

During time I've developed my own style which feels good. My whole project (3d engine) uses this style, but never takes into account if parameters passed to a function can be modified or not, that's why I'm approaching this 'wider' then just one source file.

For example:

- I have a d3d class, which is the main class where the rendering happens

- for example the 'RenderFrame' member function, takes a d3dscene and other objects as parameters, but they're never changed

(and therefore would be safer to make them 'const'). At the moment I pass basically everything as a pointer, meaning I could accidentally change everything and can't see in a (member) function what the passed parameters/ variables are used for

- the same 'RenderFrame' function uses variables of the d3d object, but never changes them, so the member function 'RenderFrame' should be 'const' to (for safety)

etc. :)

One of the things I've put through over my complete project is variable namings.

mMyThing, means it's a class member, starting with "m", pMyOther, means it's a parameter given to the scope/ function, because it starts with 'p'.

It was quite a job to go through all code and apply it, but it definately helped and helps me when I change things now.

The same is with documentation/ comments in my code, also one style all over the engine.

Basically it's to late to prevent OCD, as you can read :)

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Advertisement

But if in your examples you confuse the syntax for pointers and references I feel you need to be OCD in other areas. I personally like the p prefix for pointers since the syntax is different ("->" vs. ".").

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley
I wont judge the style that works for you :)
After my changes I'll be able to recognize that variables that can be altered use '->' and other passed objects/parameters use the '.'.
Members and function params I distinct with the m and p prefix.

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Thanks, I didn't know that.

So to be sure, this would be correct:


class MyClass

{
public:
   int mAge;

   void DoSometingWithNoneMembers(const float p1, float *p2) const;
   void UpdateAge(const int &pAge);
}

void MyClass::DoSometingWithNoneMembers(const float p1, float *p2)

{
   p2 = p1;
}

void MyClass:UpdateAge(const int &pAge)
{
   mAge = *pAge;
}

Where I assume that the 'const' keyword for member functions is only needed in the prototype.

Is this correct, or does is also have to be in the implementation? (sounds logical for readability if it's also there)

Sorta. UpdateAge is properly non const. But DoSometingWithNoneMembers shouldn't be a method at all, since it doesn't do anything with the object. A more typical example of a const method would be something that returns a value based on the members. For example:


int MyClass::getDogYears() const
{
  return mAge*7;
}

Yep, I understand.

An example in my case:


bool CD3d::CheckDevice() const
{
	if(SUCCEEDED(mD3ddev->TestCooperativeLevel())) return true;
	return false;
}

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Thanks.

Can you explain a bit more what you mean with making member functions const-correct?

I think it begins with the passed objects to the functions, which should or shouldn't be modified (and prevent copying variables when not needed).

Unless of course, the basics behind are not OK (structure of the classes, what's dependent on what, which member functions should be smaller/ split up etc.).

Not sure if this is the case 100%, but anyway this first step feels like good practice. Next could be to see if I can make it more efficient/ with smaller/ other member functions.

Or do you mean something else?

This should help:

http://en.wikipedia.org/wiki/Const-correctness

[C++ FAQ / Section 18] Const correctness: http://www.parashift.com/c++-faq/const-correctness.html
In particular:
- http://www.parashift.com/c++-faq/overview-const.html
- http://www.parashift.com/c++-faq/const-and-type-safety.html
GotW #6a: http://herbsutter.com/2013/05/24/gotw-6a-const-correctness-part-1-3/
GotW #6b: http://herbsutter.com/2013/05/28/gotw-6b-solution-const-correctness-part-2/

** when it regards passing 'simple' objects like a vector/vertex, matrix, int, float etc., that is only input (not to be changed), I use const only (no reference). For example:
float DistCoordToCoord(const D3DXVERTEX3 pVector1, const D3DXVECTOR3 pVector2); or

** when it regards passing 'simple' objects which need to be altered, I use a pointer. For example:
void DistCoordToCoord(const D3DXVERTEX3 pVector1, const D3DXVECTOR3 pVector2, float *pResult);



This is a code smell to me. If pResult is an output of the function then it should be returned.


float DistCoordToCoord(const D3DXVERTEX3 pVector1, const D3DXVECTOR3 pVector2);

If you need the initial value for some reason, pass that in.


float DistCoordToCoord(const D3DXVERTEX3 pVector1, const D3DXVECTOR3 pVector2, float initialValue);


Then do the assignment in the call


float someValue = 10f;
someValue = DistCoordToCoord(vector1, vector2, someValue);



Side note: If you're going to prefix p to pointers, make sure you're consistent about it. pVector1 and pVector2 are poorly named.
Even more side note: Why not make them references here? Sure, you're only saving a few bytes, but it costs you nothing in terms of readability and code maintenance.

if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight
Thanks.
You're absolutely right on referencing also d3dxvector3 objects etc.

On the naming, pVector, pPos, pRange etc. Works for me, because I name all function parameters p... and all my class members are named m....

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

float DistCoordToCoord(const D3DXVERTEX3 pVector1, const D3DXVECTOR3 pVector2);

This is going to invoke the copy constructor for pVector1 and pVector2, create new copies of each, and put them on the stack. Not a big deal for a D3DXVECTOR3, but you need to be real careful if doing it with other object types.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Clear, unless its just a float or an int, I'll also pass the other parameters by reference (vectors, strings etc.).
This will primarily also keel my code clear and readable (the few saved bytes are just a bonus :))

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

This topic is closed to new replies.

Advertisement