2013-03-12 4 views
0

Я пытаюсь создать абстрактный класс, из которого могут быть основаны некоторые другие классы для проекта arduino. Но всякий раз, когда я вызываю метод, который является виртуальным в базе, он просто вызывает базовую реализацию. Код ниже. Может ли кто-нибудь увидеть, что я делаю неправильно?Оверлейные виртуальные методы, которые не называются

#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(); 
+2

Возможно, вы испытываете нарезку объектов. – chris

+0

Вы 1) определяете функции в производном классе и 2) не разрезаете, правильно? Также класс не является абстрактным, если в нем нет хотя бы одной чистой виртуальной функции-члена, которой у вас нет. –

+0

Вам нужно будет показать пример вашего использования. Как создается экземпляр класса, как он превращается в базовый класс и как вы вызываете функцию? –

ответ

2

У вас есть код:

RTC_Base RTC = RTC_DS1307(); 
DateTime dt = RTC.now(); //The above call just returns a blank DateTime(); 

Это object slicing (как изначально догадывался @ Крис). Для работы Polymorphism вам придется притворяться, что ваш производный класс является базовым классом, обрабатывая указатель или ссылку в качестве базы, когда он действительно является адресом производного. (Потому что Derived фактически содержит Base внутри него).

Derived myDerived; 
Base &myBaseRef = myDerived; 

myBaseRef.myVirtualFunction(); 

В противном случае, вы создаете производный, и пытаетесь заставить байты в Базу, и потерять все производное байтовые. Это не хорошо! =)

Дело в том, что на самом деле вы не должны быть конвертирования выведенного на базу, просто доступа к производному, как если бы это была база. Если вы конвертируете его в базу, то - база. И ваш базовый класс возвращает пустой DateTime.

Для этого с динамически распределяемой памяти, вы можете сделать это:

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. 

Если вы используете C++ 11, вы можете позволить std::unique_ptr обрабатывать жизни объекта для вас, так что вы не» t необходимо помнить, чтобы называть «удалить»:

std::unique_ptr<Base> myBase; 

//Later... 
myBase = new Derived; 
myBase->myVirtualFunction(); 

//Automatically freed when the myBase smart pointer goes out of scope... 
+0

Я * думаю *, что имеет смысл ... Есть ли хороший способ сделать это, чтобы RTC_Base & RTC могла быть глобальной переменной (а не задавать что-либо до метода setup())? Кроме того, можно ли это сделать и все еще иметь базу, содержащую чистые виртуальные машины? –

+0

Я просто получаю ошибку: «RTC» объявлен как ссылка, но не инициализирован «когда я пытаюсь сделать его глобальным без немедленного init –

+0

Конечно, используйте указатель вместо ссылки. RTC_Base * globalBase = NULL; Позже: globalBase = new Derived; Просто убедитесь, что вы вызываете «delete» на globalBase, поскольку вы динамически выделяете память. («удалить» все, что вам нужно ») –

Смежные вопросы