简体   繁体   中英

Explicitly calling WINAPI ReadFile()

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.

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's declarator-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 of X (10.2), or
  • if X is a nested class of class Y (9.7), shall be a member of Y , or shall be a member of a base class of Y (this lookup applies in turn to Y '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 class X in a block enclosing the definition of class X , or
  • if X is a member of namespace N , or is a nested class of a class that is a member of N , or is a local class or a nested class within a local class of a function that is a member of N , before the member function definition, in namespace N or in one of N '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 class X or used in the mem-initializer for a constructor of class X , if name lookup (3.4.1) resolves the name in the id-expression to a nonstatic nontype member of class X or of a base class of X , the id-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.

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