0

I am trying to work out how to do this, so I have an example class called myClass:

//In myClass.h
Class myClass
{
    private:

    GLuint id;
};

//In myClass.cpp, in one of the functions
glGenBuffers(1, &myClass::id);

So glGenBuffers wants the address of a GLuint to assign the ID of the buffer to but when I try to do this I get the compilation error:

Cannot convert 'GLuint myClass::*' to 'GLuint*' in argument passing

DomAyre
  • 828
  • 1
  • 11
  • 23

3 Answers3

4

//In myClass.cpp, in one of the functions

If by this you mean in one of myClass's non-static member functions, then you can simply:

glGenBuffers(1, &id);
John Dibling
  • 99,718
  • 31
  • 186
  • 324
3

You could be forgiven for expecting this to work, if called from within a non-static member function of myClass. For instance, this works:

GLuint x = myClass::id;

More mysteriously, this works too:

glGenBuffers(1, &(myClass::id));

Similarly:

GLuint *p = &myClass::id;   // Doesn't work!
GLuint *p = &(myClass::id); // Works!

As John Dibling wrote, in general the solution is simply to omit the scope qualifier:

GLuint x = id;
glGenBuffers(1, &id);

But this won't work if you are trying to access a member in a base class that has the same name. So what is the difference between &myClass::id and &(myClass::id)? I wish I could tell you, but I can't figure it out! The scope operator :: has the highest precedence of all the C++ operators, so I would expect them to be equivalent. Can anybody put me right?

Edited to add: OK, it all makes some kind of sense. In the draft standard N3337 for C++0x, it says:

The result of the unary & operator is a pointer to its operand. The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static member m of some class C with type T, the result has type “pointer to member of class C of type T” and is a prvalue designating C::m. Otherwise...

Then you go and look up what a qualified_id is, and it turns out that if you put it in parentheses, it's not a qualified_id any more. Which explains everything.

TonyK
  • 16,761
  • 4
  • 37
  • 72
  • There's nothing mysterious here. Scope resolution is the tool used when ambiguity occurs. If `myClass` had a base class with its own `id` member, you'd have to use scope resolution. Either `&this->myClass::id` (see why `this->` is useful :P) or simply `&(myClass::id)`. – StoryTeller - Unslander Monica Jul 22 '14 at 15:47
  • @StoryTeller: So why do you need the parentheses? I am still searching through the C++ standard document, looking for a paragraph about the special case `&::`. I'll let you know if I find it! – TonyK Jul 22 '14 at 15:53
  • The ones that don't work are returning a pointer to member, there's a question about it [here](http://stackoverflow.com/questions/670734/c-pointer-to-class-data-member). It seems like a very confusing syntax though! – dshepherd Jul 22 '14 at 15:55
  • Because without them you get a pointer to member type. That's the syntax, for all its convoluted glory – StoryTeller - Unslander Monica Jul 22 '14 at 15:55
  • 1
    `myClass::id` is a _qualified-id_, `(myClass::id)` is a _primary-expression_. Similar to the difference between `decltype(a)` and `decltype((a))`. – Oktalist Jul 22 '14 at 15:56
  • 1
    `5.3.1.3` _If the operand is a qualified-id naming a non-static member m of some class C with type T, the result has type "pointer to member of class C of type T"... if the type of the expression is T, the result has type "pointer to T"..._ `5.3.1.4` _A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed in parentheses._ – Oktalist Jul 22 '14 at 16:01
  • @Oktalist: We agree exactly! Thank you for confirming my diagnosis. – TonyK Jul 22 '14 at 16:07
0

Firstly, you need to understand the difference between a class and an object. A class is a blueprint, an object is an instance of a class - ie an actual thing that you can manipulate. (similar to a cookie cutter and a cookie - the cutter just provides the shape the cookie will be, once you've cut one, or two, or many cookies out of a big heap of dough)

So.. you either have to instantiate an object to access the id, or you have to specify that there is a single 'global' id by using the static keyword.

gbjbaanb
  • 51,617
  • 12
  • 104
  • 148
  • The word "template" can be misleading considering templates in C++ are their own thing. – chris Jul 22 '14 at 15:01
  • 1
    A member does not have to be `public` in order to pass its address as a function parameter. Also, "blueprint" might be netter (less confusing) than "template". – John Dibling Jul 22 '14 at 15:06
  • @JohnDibling thanks, I would have finished my answer - but work called :( – gbjbaanb Jul 22 '14 at 15:52