Reputation: 11
I'm working with a Garmin GPS device, and trying to pull info off it relating to latitude, longitude, etc. through USB. I was working within the SDK and got to the point I could pull this info out, so now I'm working on rolling this code into the system I'm working in.
This code is being placed in a class: CGarminUSBEngine which inherits from CASCIIEngine
I pull this info off the device using the code
ReadFile (gHandle,
TheNewBuffer,
MAX_BUFFER_SIZE,
&theBytesReturned,
NULL);
My issue is that the CASCIIEngine from which CGarminUSBEngine inherits has the function
BOOL ReadFile(void)
and when I try to call ReadFile() with 5 paramaters to read from my USB device, I get a compiler error saying "'CASCIIEngine::Readfile' : function does not take 5 arguments"
I have yet to figure out how to explicitly call the WINAPI version of this ReadFile() function, or even why it would be necessary. It seems to me that the compiler should know ReadFile is overloaded, and I'm trying to call the WINAPI version, not the CASCIIEngine version.
Mainly I'd like to know how to explicitly call the WINAPI version, and secondly I'd like to know exactly why this is necessary. Perhaps its somthing simple I'm just missing, which would be frustrating. I appriciate any help.
Upvotes: 1
Views: 627
Reputation: 52217
You're getting the error because the compiler is resolving the call to CASCIIEngine::Readfile()
instead of the global ReadFile()
function provided by the Windows API†.
Obviously the number of arguments don't match, so the compiler complains.
To tell the compiler to refer to the global ReadFile()
function, use the ::
scope resolution operator.
::ReadFile (gHandle, TheNewBuffer, MAX_BUFFER_SIZE, &theBytesReturned, NULL);
// ^^---- Note `::`
† The exact rules that determine which function is resolved is laid out in great detail in the C++ standard. The relevant clauses to your situation are as follows:
3.4.1 Unqualified name lookup [basic.lookup.unqual]
1. In all the cases listed in 3.4.1, the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name. If no declaration is found, the program is ill-formed.
...
8. A name used in the definition of a member function (9.3) of class
X
following the function’sdeclarator-id
shall be declared in one of the following ways:
- before its use in the block in which it is used or in an enclosing block (6.3), or
- shall be a member of class
X
or be a member of a base class ofX
(10.2), or- if
X
is a nested class of classY
(9.7), shall be a member ofY
, or shall be a member of a base class ofY
(this lookup applies in turn toY
’s enclosing classes, starting with the innermost enclosing class), or- if
X
is a local class (9.8) or is a nested class of a local class, before the definition of classX
in a block enclosing the definition of classX
, or- if
X
is a member of namespaceN
, or is a nested class of a class that is a member ofN
, or is a local class or a nested class within a local class of a function that is a member ofN
, before the member function definition, in namespaceN
or in one ofN
’s enclosing namespaces....
9.3.1 Nonstatic member functions [class.mfct.nonstatic]
2. When an
id-expression
(5.1) that is not part of a class member access syntax (5.2.5) and not used to form a pointer to member (5.3.1) is used in the body of a nonstatic member function of classX
or used in themem-initializer
for a constructor of classX
, if name lookup (3.4.1) resolves the name in theid-expression
to a nonstatic nontype member of classX
or of a base class ofX
, theid-expression
is transformed into a class member access expression (5.2.5) using(*this)
(9.3.2) as the postfix-expression to the left of the.
operator. The member name then refers to the member of the object for which the function is called ...
Per 3.4.1/1 and 3.4.1/8, the declaration for ReadFile()
in the CASCIIEngine
class was found first (second bullet point), before the ReadFile()
in the global namespace (last bullet point), so name lookup resolves to the member function.
That means your call to ReadFile()
in your class is actually being resolved to this:
(*this).ReadFile(gHandle, TheNewBuffer, MAX_BUFFER_SIZE,
&theBytesReturned, NULL); // Per 9.3.1/2
So the global function wasn't even considered for overload resolution, because it wasn't a member function.
When you use the ::
scope resolution operator in the manner used above, it becomes a qualified name referring to a name in the global namespace and thus the above rules do not apply.
Upvotes: 7