Forums

PIC/dsPIC development

Started by bitrex November 4, 2018
On 11/08/2018 09:01 AM, TTman wrote:
> SNIP... > >>> >>> Certainly templates are extremely useful.  And their reputation for >>> "code bloat", especially in small embedded systems, is both unfair and >>> outdated.  But you don't /need/ templates in order to take advantage of >>> C++ in your programming.  After all, why worry about static polymorphism >>> compared to runtime polymorphism, when you can do a great deal of useful >>> programming with classes without polymorphism at all? >>> >>>> Virtual methods have their place even in uP development but it makes >>>> sense to use them sparingly particularly on the Harvard architecture >>>> with limited SRAM; the standard insists on copying all vtables out of >>>> Flash into SRAM at runtime even though in theory this should not be >>>> necessary. >>> >> > All the above is why I just never got to grips with HLL... My programmer > that I employed back in the day used Delphi/ Borland Pascal to great > effect on PCs... but then he had an honors in Maths...
"virtual" methods are basically a variation on function pointers but dynamically dispatched and in the case of inheritance can be called thru the base class pointer, a sort of silly motivational example follows. This is the compiler output: <https://godbolt.org/z/fDOAPt> At the end of it you'll see the compiler has generated a small "hidden" function pointer table in memory for each subtype of Vehicle: vtable for Car: .short 0 .short 0 .short _ZN3CarD1Ev .short Car::~Car() [deleting destructor] .short Car::start() const vtable for Truck: .short 0 .short 0 .short _ZN5TruckD1Ev .short Truck::~Truck() [deleting destructor] .short Truck::start() const When a "start" method is called in "main" by the programmer through the base class pointer the compiler automatically generates code to load the appropriate function pointer for the type of Vehicle from the table into memory and call the appropriate function. MOV.W #vtable for Car+4, @R12 // offset points to Car::start() MOV.W R12, -8(R4) MOV.B #2, R12 CALL R10 // call it MOV.W #vtable for Car+4, @R12 MOV.W R12, -6(R4) MOV.B #2, R12 CALL R10 MOV.W #vtable for Truck+4, @R12 MOV.W R12, -4(R4) MOV.B #2, R12 CALL R10 MOV.W #vtable for Truck+4, @R12 MOV.W R12, -2(R4) MOV.B #0, R8 #include <cstdint> class Vehicle { public: /* base class virtual destructor, when any derived object is destroyed and memory resources are freed, if this base class held resources they would be freed up automatically too */ virtual ~Vehicle() = default; /* pure virtual function, must be overriden in derived class */ virtual void start() const = 0; protected: /* Constructor is protected, a Vehicle is just an "interface" class it can't be created by itself without specialization */ Vehicle() = default; }; class Car : public Vehicle { public: /* specialization for Cars */ void start() const override { //specific algorithm for Cars } }; class Truck : public Vehicle { public: /* specialization for Trucks */ void start() const override { //specific algorithm for Trucks } }; int main() { const std::size_t garage_size = 4; Vehicle* garage[garage_size]; garage[0] = new Car(); garage[1] = new Car(); garage[2] = new Truck(); garage[3] = new Truck(); /* start them all */ for (std::size_t i = 0; i < 4; ++i) { garage[i]->start(); } /* swap out for new vehicle */ delete garage[0]; garage[0] = new Truck(); /* clean up when done */ for (std::size_t i = 0; i < 4; ++i) { delete garage[i]; } }
> --- > This email has been checked for viruses by Avast antivirus software. > https://www.avast.com/antivirus >