This is more a C++ and Object Oriented Programming question than an openFrameworks one :
I have an app that needs a printer. This printer can be of multiple types :
standard printer via CUPS using a system command line
WiFi printer
Thermal printer tied to serial port over USB which uses an external addon (ofxThermalPrinter)
I have read a lot about inheritance and polymorphism, but i am afraid i didn’t understand every subtle aspect of it. I am not very familiar with inheritance which i don’t often use, but for this purpose it sounds it would be the wise solution ?
So as i understand, i would need (?) :
a BasePrinter class
a PrinterCUPS class derived from BasePrinter
a PrinterWIFI class derived from BasePrinter
a PrinterThermal class derived from BasePrinter and ofxThermalPrinter
now, here are some constraints
All printers have a print() method
only WiFi and Serial printers have a close() method
From what i see for my purpose, i don’t think i would need the BasePrinter as every printer would print differently.
So i imagine i would need abstract class ?
this is what i have so far (just for ThermalPrinter type)
#include <printer.h>
#include <ofxThermalPrinter.h>
class ThermalPrinter : public Printer, public ofxThermalPrinter {
public:
ThermalPrinter();
virtual ~ThermalPrinter();
virtual void print();
};
Do i need to use pointers ?
How to manage use of those printers ? do i have to declare BasePrinter objects or specific objects related to their nature (CUPS, WiFi etc…) ?
If anyone could help me sort this out, this would be great !
This is just a pragmatic advice, not too much of a software engineering one:
For your need, you can see your base class as the class you want to interact with, while not having to worry about the underlying details. So you could define your base class with all the functions you may need (open, print, close), and if a specific printer doesn’t need that function, just make the implementation for that specific printer return immediately.
A decent example of this approach is for ofVideoPlayer that hides the complexity of interfacing with various native code and offer a common interface to all platforms.
Note: the problem with this approach is that it’s really rigid and if you need to make structural changes to your code it can get painful (for example with ofVideoPlayer, the update() function is not virtual ( I believe) and will copy the pixels given by the native video player into a texture. But if you have a special video player that gives you a texture, and you’d want to get the pixels (ie the opposite process) everything falls apart because of the early assumption Pixels go to texture and not the other way)
@Gallo the way you are doing it is correct, just define everything as pure virtual, virtual void func()=0; since your classes don’t share any implementation details. that still allows you to use objects of different types on a vector for example (polymorphishm) but as you say you need to use pointers then.
You can create your objects normally but if you need to use them as the base class then you need a pointer or reference, smart pointers like shared_ptr or unique_ptr also work.
Putting implementation details or variables into base classes (inheritance) is usually a source of problems and makes the code hard to understand if you need some common functionality it’s usually better to have an external class or function that you call from everywhere that implements that funcitonality. For example instead of: