Help understanding Print::write()--it calls write()--where is write() defined? Help reading code
write is implemented in the class that inherits the Print class - such as HardwareSerial.

There are a number of write functions, and they are overloaded, which means that they are all distinct functions identified using their parameters as well as their name (write(uint8_t) and write(uint8_t *, size_t) are different functions).  The child class overrides the write(uint8_t) function that is pure virtual1 in the main Print class, but the other write functions with other parameter lists aren't overridden and are just "used".

The using Print::write tells it "the write functions to which I am referring are from the Print class."


  Using-declaration introduces a member of a base class into the derived class definition, such as to expose a protected member of base as public member of derived. In this case, nested-name-specifier must name a base class of the one being defined. If the name is the name of an overloaded member function of the base class, all base class member functions with that name are introduced. If the derived class already has a member with the same name, parameter list, and qualifications, the derived class member hides or overrides (doesn't conflict with) the member that is introduced from the base class.


I'm not entirely sure why they feel they need to use it, since the write functon(s) in Print are public and thus exposed already.


  What does it mean/how does it work defining functions in .h files? I've never done this before


Exactly the same as if you had defined the function in a .cpp file, but with a few minor differences, the most important one of which is that the compiler finds it easier to inline the function (or if you're really lucky eradicate the function altogether). It's great for simple functions such as setters and getters that just set or return the value of a variable. In such cases inlining is desirable, and the compiler may even be able to replace the entire function with just direct access to the variable (if it's clever enough).

Another important thing to note with functions in .h files is that you can only really do it with class member functions or static functions. Otherwise you end up with compilation errors complaining about multiple definitions if you use the header file in more than one place.




1: A Pure Virtual function (such as virtual size_t write(uint8_t) = 0;) is one which has to be implemented in the child class. Failure to implement it results in a compilation error. The pure virtual function defines part of the interface but doesn't implement the software for it - that is down to the child class to implement.