Why is Print and abstract class?

Why is Print and abstract class? Line #51 of Print.h is:

virtual size_t write(uint8_t) = 0;

which is a pure virtual function which make the entire class abstract. Shouldn't this line of code be removed, especially since the method:

size_t write(const char *str) {
if (str == NULL) return 0;
return write((const uint8_t *)str, strlen(str));
}

exists immediately below it. I don't know what's going on, but I suspect that whomever wrote the write function forgot to remove the pure virtual declaration after they were done. Anyone?

Functions "write(x)" and "write(x, y)" are virtual because the class does not know how the data is to be written. Serial writes the data in one way whilst File writes in another way. By making the "write" functions abstract, any implementation of the Print class forces the developer to write those functions for the specific purpose.

because write(byte) is to be implemented by the derived classes

noiasca:
juraj, where does this model come from? (and are there other ones?)

I created it with an UML tool.

this is the only one complex class hierarchy in Arduino

If you have an object of type "Print", what would you have the function 'write(uint8_t)' do? The class 'Print' has no use except to put the characters somewhere. If you created a derived class you would certainly want to be told "You forgot to implement the function 'write(uint8_t)' so your derived class is useless."

Thank you all for you excellent explanations. Unfortunately, I see now that I asked the wrong question, starting from the top down. I should have started from the bottom up, which I will do now in the hope of making my question better understood.

In my current project, I include a number of standard libraries – LiquidCrystal_I2C, SD, Ethernet and many others. The three libraries just mentioned all generate the same error:

'Object of abstract class type “[various]” is not allowed: pure virtual function “Print::write(uint8_t)” has no overrider'

These libraries are all unmodified direct downloads using Arduino's library manager. They all (obviously) subclass from object “Print”, and have failed to provide a write(uint8_t) method to override the pure virtual method of the same signature from that parent object.

This surprises me. As a consumer of the standard Arduino libraries, am I expected to modify those libraries before I can use them? What purpose does a write(uint8_t) method have in the Ethernet library? How would I know? Am I expected to study the code of the entire library to find out? Where is the documentation for the design of this library (it's certainly NOT in the actual code).

In other words, if it was the intention of the authors of these libraries that I should provide my own write(uint8_t) method, I would expect some written guidelines about where and how that method fits into the overall design of the library. If it was NOT their intention that I should write the method, then the authors should have written one for me, so their classes are NO LONGER ABSTRACT and can be used (or even subclassed) in my own code.

That is my situation, which prompted me to ask why Print is an abstract class in the first place. I understand the reasons for having pure virtual methods, and they all have to do with requiring the end user to provide a necessary method which can't be anticipated by the original authors. I get that. What I don't get is what purpose the write(uint8_t) function plays in the Ethernet (or SD, or LiquidCrystal_I2C) library, so I have some clue as to what I should be writing. Sorry for the confusion.

If you're getting those errors, then something else is wrong -- could be your code, the libraries' installation, the IDE's installation, etc. Have you tried the example programs that come with each library? They are known to work and typically don't involve many other libraries.

Would be quite helpful if you would post the actual errors instead of a description thereof :slight_smile:

What you should have done is posted your code and your errors, both complete and verbatim,
plus told us which board setting you used, and which version of the Arduino code you have, so that there's enough information to identify your problem...

Development Host: MSI Titan, Windows 8.1, x64
Development Platform: Visual Studio 2019
Arduino IDE for Visual Studio by Visual Mirco 19.0
Arduino Platform: 1.8.12 (latest)
Arduino Library: Ethernet 2.0 (latest)
Arduino HW: Official Mega 2560 and official Ethernet 2 shield

A picture is worth a thousand words:

A method to override “Print::write(uint8_t)” has NOT been provided, leaving class EthernetServer and EthernetUDP as ABSTRACT classes.

In the library here: GitHub - arduino-libraries/Ethernet: Ethernet Library for Arduino, the EthernetServer class does indeed implement the write function. What library are you using?

odlumb:
A method to override “Print::write(uint8_t)” has NOT been provided, leaving class EthernetServer and EthernetUDP as ABSTRACT classes.

In Eclipse the presentation compiler shows this too until I open the .h file.
but the build doesn't have the error.

What library am I using? Well, at the top of Ethernet.h it reads "Copyright 2018 Paul Stoffregen". It does indeed have a write(uint8_t) method. Here is the error:

I use the built in tools in Visual Micro to retrieve and install libraries. This is a picture of that tool showing which Ethernet library is installed:

What you are showing is "problem" with the plugin scanner itself and has nothing to do with C++/Arduino tools.

Try to compile your code, if it splits out errors, we can deal with those errors. Other than that you need to contact the plugin creator and let them know of these issues.

Thank you, good to know. I will contact Visual Micro.