Reputation: 31359
I'm trying to create an abstract class that some other classes can be based off of for an arduino project. But, whenever I call a method that is virtual in the base, it just calls the base implementation. Code below. Can anyone see what I'm doing wrong?
#define RTCBASE 0
class RTC_Base {
public:
virtual uint8_t begin(void){ return 0; };
virtual void adjust(const DateTime& dt){};
virtual DateTime now(){ return DateTime(); };
virtual int Type(){ return RTCBASE; };
};
////////////////////////////////////////////////////////////////////////////////
// RTC based on the DS1307 chip connected via I2C and the Wire library
#define DS1307 1
class RTC_DS1307 : public RTC_Base
{
public:
virtual int Type(){
return DS1307;
}
uint8_t begin(void);
void adjust(const DateTime& dt);
uint8_t isrunning(void);
DateTime now();
uint8_t readMemory(uint8_t offset, uint8_t* data, uint8_t length);
uint8_t writeMemory(uint8_t offset, uint8_t* data, uint8_t length);
};
///In Code
RTC_Base RTC = RTC_DS1307();
DateTime dt = RTC.now();
//The above call just returns a blank DateTime();
Upvotes: 0
Views: 2499
Reputation: 10495
You have the code:
RTC_Base RTC = RTC_DS1307();
DateTime dt = RTC.now(); //The above call just returns a blank DateTime();
That's object slicing (as @chris originally guessed). For Polymorphism to work, you'll have to pretend your derived class is a base class, by treating a pointer or reference as a Base, when it really is the address of a Derived. (Because the Derived actually contains the Base within it).
Derived myDerived;
Base &myBaseRef = myDerived;
myBaseRef.myVirtualFunction();
Otherwise, you are creating a Derived, and trying to force the bytes into a Base, and losing all the Derived's bytes. It's not good! =)
The point is, you shouldn't actually be converting the Derived to a Base, just accessing the Derived as if it were a Base. If you convert it to a Base, it is a base. And your Base class returns an empty DateTime.
To do so with dynamically allocated memory, you can do this:
Base *myBase = nullptr; //Or 'NULL' if you aren't using C++11
myBase = new Derived;
myBase->myVirtualFunction(); //Dereference the myBase pointer and call the function.
delete myBase; //Free the memory when you are finished.
If you are using C++11, you can let std::unique_ptr handle the lifetime of the object for you, so you don't have to remember to call 'delete':
std::unique_ptr<Base> myBase;
//Later...
myBase = new Derived;
myBase->myVirtualFunction();
//Automatically freed when the myBase smart pointer goes out of scope...
Upvotes: 2