简体   繁体   中英

Doom 3 source: why does a class representing 2-vectors overload the subscript operator twice?

I thought I'd try beefing up my C++ and OpenGL by looking at the recently-released Doom 3 source. Much learned so far, but I've hit a wall. The class detailed here has methods

float  operator[] (int index) const  

and

float &  operator[] (int index) 

whose bodies both read

return ( &x )[ index ];

where x is one of the class' two data members (the other being y ; this class is for 2-vectors).

While I can understand the syntax of each version's header/prototype, I don't get why they're both present.

const seems to appear (or not appear, as preferred) only to distinguish the headers sufficiently to allow compilation. (That is, remove const and VS2010 refuses to compile, similarly if both headers end in const .)

And why return a ref to a float? None of the class' seven other float-type methods do this, so I'm guessing efficiency isn't a factor (tho' maybe this operator's called vastly more often than the others).

Appreciate any insight as to what's going on here...

This is a common idiom (known as "const overloading"). See the C++ FAQ: http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.12 .

The ambiguity is resolved by whether *this is const or not. On a const object, the const overload is called, in which case it acts in a read-only style. On a non- const object, the non- const is called, in which case it acts in a read/write style.

Note, crucially, that this is not a way of distinguishing between read and write accesses.

Think of them as a related pair of getter and setter methods for subscripted elements. The float & operator[](int index) is the setter version and allows you to use syntax like so:

theObject[anIndex] = 1.0;

This requires that theObject is available to you as a non- const object (or through an Object * or Object & ).

In the case without const, you are using a reference because you want to change the value when calling the function. Eg setting a value: a[11] = 5.0;

The case with const is added because other functions can only be declared as const functions if all other functions that they call are also const functions.

And why return a ref to a float?

The reason to return a reference to a float is to allow the caller to modify that float. (By the way, efficiency wouldn't be a reason for this, since pointers tend to be at least as big as floats, so the extra indirection is pure cost.)

const at the end of a method signature indicates that it can safely be called on a const object/reference/expression. So, if v is an idVec2 , then v[0] may be used as an lvalue (and v[0] = 3.0f will actually set v[0] ), but if v is a const idVec2 , then v[0] can only be used as an rvalue (meaning that v[0] = 3.0f is ilegal).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM