【发布时间】:2019-04-29 01:58:42
【问题描述】:
我刚学c++,继承有问题,有c#背景,感觉C++的继承有点复杂。
我有一个基类 UserInterface,它具有虚拟和纯虚拟方法:
class UserInterface
{
protected:
LiquidCrystal* lcd;
const int ICON_WATER_DROP = 0;
const int ICON_SMILEY = 1;
const int ICON_STATION = 2;
const int ICON_WATER_DROPS = 3;
const int ICON_ALARM = 4;
const int ICON_PRESSURE = 5;
/* icon for water drop */
byte waterDrop[8] =
{
B00100,
B00100,
B01010,
B01010,
B10001,
B10001,
B10001,
B01110
};
byte bucket[8] =
{
B01010,
B00100,
B00010,
B11111,
B10001,
B11111,
B10001,
B11111
};
/* smiley face */
byte smiley[8] =
{
B00000,
B10001,
B00000,
B00000,
B10001,
B01110,
B00000,
B00000
};
byte station[8] =
{
B11110,
B10010,
B11111,
B10011,
B10011,
B10011,
B10010,
B11111
};
byte alarm[8] =
{
B00000,
B00100,
B01110,
B01110,
B01110,
B11111,
B00100,
B00000
};
byte pressure[8] =
{
B00100,
B01110,
B11111,
B00100,
B00100,
B11111,
B01110,
B00100
};
public:
UserInterface();
virtual ~UserInterface();
virtual void drawIcon(int icon);
virtual void drawInitializingScreen();
virtual void clearScreen();
virtual void drawText(const __FlashStringHelper *line1);
virtual void drawText(const __FlashStringHelper *line1, const __FlashStringHelper *line2);
virtual void drawText(const __FlashStringHelper *line1, int line2);
virtual void drawAddressSetupScreen(int address);
// All this methods need to be implemented by each subclass
virtual void drawHomeScreen(byte address) = 0;
virtual void drawWateringTotalVolumeScreen(char* remainingTime, char* litres) = 0;
virtual void drawWateringVolumePerMinuteScreen(char* remainingTime, char* litres) = 0;
virtual void drawWateringPressureScreen(char* remainingTime, char* presure) = 0;
virtual void drawWateringPausedScreen(char* remainingTime) = 0;
virtual void drawWateringPausedAlternateScreen(char* remainingTime) = 0;
virtual void drawOutOfService(byte address) = 0;
virtual void drawInvalidSelection() = 0;
};
和类实现:
UserInterface::UserInterface()
{
//lcd = new LiquidCrystal(12, 11, 5, 4, 3, 2);
lcd = new LiquidCrystal(5, 6, 7, 8, 9, 10);
lcd->clear();
// create a new custom characters
lcd->createChar(ICON_WATER_DROP, waterDrop);
lcd->createChar(ICON_SMILEY, smiley);
lcd->createChar(ICON_STATION, station);
lcd->createChar(ICON_WATER_DROPS, bucket);
lcd->createChar(ICON_ALARM, alarm);
lcd->createChar(ICON_PRESSURE, pressure);
}
UserInterface::~UserInterface()
{
}
void UserInterface::drawIcon(int icon)
{
// print the custom char to the lcd
lcd->write(icon);
}
void UserInterface::drawInitializingScreen()
{
lcd->setCursor(0, 0);
lcd->print(F("INICIALIZANDO"));
lcd->setCursor(0, 1);
lcd->print(F("VER:"));
lcd->setCursor(5, 1);
lcd->print(__DATE__);
}
void UserInterface::clearScreen()
{
lcd->clear();
}
void UserInterface::drawText(const __FlashStringHelper *line1)
{
lcd->setCursor(0, 0);
lcd->print(line1);
}
void UserInterface::drawText(const __FlashStringHelper *line1, const __FlashStringHelper *line2)
{
lcd->setCursor(0, 0);
lcd->print(line1);
lcd->setCursor(0, 1);
lcd->print(line2);
}
void UserInterface::drawText(const __FlashStringHelper *line1, int line2)
{
lcd->setCursor(0, 0);
lcd->print(line1);
lcd->setCursor(0, 1);
lcd->print(line2);
}
void UserInterface::drawAddressSetupScreen(int address)
{
lcd->setCursor(0, 0);
lcd->print(F("ADDRESS SETUP"));
lcd->setCursor(0, 1);
lcd->print(address);
}
和一个子类:
class LCD16x2: public UserInterface
{
public:
LCD16x2();
~LCD16x2();
void drawIcon(int icon);
void drawInitializingScreen();
void clearScreen();
void drawText(const __FlashStringHelper *line1);
void drawText(const __FlashStringHelper *line1, const __FlashStringHelper *line2);
void drawText(const __FlashStringHelper *line1, int line2);
void drawAddressSetupScreen(int address);
// All this methods need to be implemented by each subclass
void drawHomeScreen(byte address) override;
void drawWateringTotalVolumeScreen(char* remainingTime, char* litres) override;
void drawWateringVolumePerMinuteScreen(char* remainingTime, char* litres) override;
void drawWateringPressureScreen(char* remainingTime, char* presure) override;
void drawWateringPausedScreen(char* remainingTime) override;
void drawWateringPausedAlternateScreen(char* remainingTime) override;
void drawOutOfService(byte address) override;
void drawInvalidSelection() override;
};
和实施:
LCD16x2::LCD16x2()
{
lcd->begin(16, 2);
}
LCD16x2::~LCD16x2()
{
}
void LCD16x2::drawHomeScreen(byte address)
{
lcd->setCursor(0, 0);
lcd->print(" HUERTOS DE OCIO");
lcd->setCursor(0, 1);
lcd->write(ICON_STATION);
lcd->setCursor(3, 1);
lcd->print(F("ESTACION "));
lcd->print(address);
}
void LCD16x2::drawWateringTotalVolumeScreen(char* remainingTime, char* volume)
{
lcd->setCursor(0, 0);
lcd->print(F("RIEGO EN CURSO"));
lcd->setCursor(0, 1);
lcd->write(ICON_ALARM);
lcd->setCursor(1, 1);
lcd->print(remainingTime);
lcd->setCursor(10, 1);
lcd->write(ICON_WATER_DROP);
lcd->setCursor(11, 1);
lcd->print(volume);
}
void LCD16x2::drawWateringVolumePerMinuteScreen(char* remainingTime,
char* volumePerMinute)
{
lcd->setCursor(0, 0);
lcd->print(F("RIEGO EN CURSO"));
lcd->setCursor(0, 1);
lcd->write(ICON_ALARM);
lcd->setCursor(1, 1);
lcd->print(remainingTime);
lcd->setCursor(10, 1);
lcd->write(ICON_WATER_DROPS);
lcd->setCursor(11, 1);
lcd->print(volumePerMinute);
}
void LCD16x2::drawWateringPressureScreen(char* remainingTime, char* pressure)
{
lcd->setCursor(0, 0);
lcd->print(F("RIEGO EN CURSO"));
lcd->setCursor(0, 1);
lcd->write(ICON_ALARM);
lcd->setCursor(1, 1);
lcd->print(remainingTime);
lcd->setCursor(10, 1);
lcd->write(ICON_PRESSURE);
lcd->setCursor(11, 1);
lcd->print(pressure);
}
void LCD16x2::drawWateringPausedScreen(char* remainingTime)
{
lcd->setCursor(0, 0);
lcd->print(F("RIEGO EN PAUSA"));
lcd->setCursor(0, 1);
lcd->print(remainingTime);
}
void LCD16x2::drawWateringPausedAlternateScreen(char* remainingTime)
{
drawWateringPausedScreen(remainingTime);
}
void LCD16x2::drawOutOfService(byte address)
{
lcd->setCursor(3, 0);
lcd->print(F("ESTACION "));
lcd->print(address);
lcd->setCursor(0, 1);
lcd->print(F("FUERA DE SERVICIO"));
}
void LCD16x2::drawInvalidSelection()
{
lcd->setCursor(0, 1);
lcd->print(F("SELECCION"));
lcd->setCursor(0, 2);
lcd->print(F("INVALIDA"));
}
问题在于编译器似乎无法接受对基类中实现的虚拟方法的调用:
C:\Users\marcp\AppData\Local\Temp\ccjzyoeN.ltrans2.ltrans.o:(.rodata+0x8e): 未定义引用 LCD16x2::drawIcon(int)'
C:\Users\marcp\AppData\Local\Temp\ccjzyoeN.ltrans2.ltrans.o:(.rodata+0x90): undefined reference toLCD16x2::drawInitializingScreen()'
C:\Users\marcp\AppData\Local\Temp\ccjzyoeN.ltrans2.ltrans.o:(.rodata+0x92): 未定义引用 LCD16x2::clearScreen()'
C:\Users\marcp\AppData\Local\Temp\ccjzyoeN.ltrans2.ltrans.o:(.rodata+0x94): undefined reference toLCD16x2::drawText(__FlashStringHelper const*)'
C:\Users\marcp\AppData\Local\Temp\ccjzyoeN.ltrans2.ltrans.o:(.rodata+0x96): 未定义引用LCD16x2::drawText(__FlashStringHelper const*, __FlashStringHelper const*)'
C:\Users\marcp\AppData\Local\Temp\ccjzyoeN.ltrans2.ltrans.o:(.rodata+0x98): undefined reference toLCD16x2::drawText(__FlashStringHelper const*, int)'
C:\Users\marcp\AppData\Local\Temp\ccjzyoeN.ltrans2.ltrans.o:(.rodata+0x9a): 未定义引用LCD16x2::drawAddressSetupScreen(int)'
C:\Users\marcp\AppData\Local\Temp\ccjzyoeN.ltrans3.ltrans.o: In functionupdateFirmwareCommand(unsigned char*, unsigned char*, unsigned char*)':
C:\Users\marcp\Dropbox\Source\RiegoMatic\HDO.RiegoMatic.Station.Firmware\Release/..\RMStationFirmware.cpp:1149: 未定义引用LCD16x2::clearScreen()'
C:\Users\marcp\Dropbox\Source\RiegoMatic\HDO.RiegoMatic.Station.Firmware\Release/..\RMStationFirmware.cpp:1152: undefined reference toLCD16x2::drawText(__FlashStringHelper const*, __FlashStringHelper const* )'
C:\Users\marcp\AppData\Local\Temp\ccjzyoeN.ltrans3.ltrans.o:在函数selfTest':
C:\Users\marcp\Dropbox\Source\RiegoMatic\HDO.RiegoMatic.Station.Firmware\Release/..\RMStationFirmware.cpp:693: undefined reference toLCD16x2::clearScreen()'
C:\Users\marcp\Dropbox\Source\RiegoMatic\HDO.RiegoMatic.Station.Firmware\Release/..\RMStationFirmware.cpp:704:未定义对LCD16x2::drawText(__FlashStringHelper const*, int)'
C:\Users\marcp\AppData\Local\Temp\ccjzyoeN.ltrans3.ltrans.o: In functionupdateLCD(bool)'的引用:
C:\Users\marcp\Dropbox\Source\RiegoMatic\HDO.RiegoMatic.Station.Firmware\Release/..\RMStationFirmware.cpp:160: 未定义引用LCD16x2::clearScreen()'
C:\Users\marcp\Dropbox\Source\RiegoMatic\HDO.RiegoMatic.Station.Firmware\Release/..\RMStationFirmware.cpp:169: undefined reference toLCD16x2::drawInitializingScreen()'
collect2.exe:错误:ld 返回 1 退出状态
makefile:89: 目标“RMStationFirmware.elf”的配方失败
make: *** [RMStationFirmware.elf] 错误 1
【问题讨论】:
-
你需要实现你的非纯虚函数(比如
drawIcon)。 -
我的非纯虚方法在基类中实现,我想在我的子类中使用该实现
标签: c++ inheritance