Где реализации методов SdFat BlockDriver?

Скорее всего, это скорее вопрос C++, чем вопрос Arduino; но поскольку это библиотека Arduino, спрашиваю здесь.

Я использую библиотеку SdFat для своего проекта. Библиотека определяет объект BlockDriver в одном из своих заголовков. файл, который объявляет typedef BaseDriver только для некоторых других классов.

#if ENABLE_EXTENDED_TRANSFER_CLASS || ENABLE_SDIO_CLASS
typedef BaseBlockDriver BlockDriver;
#else  // ENABLE_EXTENDED_TRANSFER_CLASS || ENABLE_SDIO_CLASS
typedef SdSpiCard BlockDriver;
#endif  // ENABLE_EXTENDED_TRANSFER_CLASS || ENABLE_SDIO_CLASS
#endif // BlockDriver_h

typedef SdSpiCard BlockDriver; мне кажется понятным. Но если ENABLE_EXTENDED_TRANSFER_CLASS или ENABLE_SDIO_CLASS определены, BlockDriver преобразуется в BaseBlockDriver. BaseBlockDriver — это абстрактный базовый класс (как определено здесь). Экземпляр объекта <code>BlockDriver</code> позже используется непосредственно в классе <code>FatVolume</code> здесь.

Мой вопрос: как определяется метод BlockDriver, когда его абстрактный базовый класс BaseBlockDriver определяется по типу BlockDriver?

, 👍1

Обсуждение

ты читал ответ?, @Juraj

Я читаю это. Мне это не до конца проясняет, поэтому я не хочу это принимать., @SpaceMonkey55

что неясно в ответе?, @Juraj

Я не очень хорошо разбираюсь в программировании, поэтому мне сложно его понять. По сути, я не понимаю, что «Typedef в BlockDriver.h предназначен только для типа указателя, а не для экземпляра объекта». означает или подразумевает. Несмотря на то, что мы объявляем его как указатель, позже мы вызываем для него методы. Как работает этот метод, если BlockDriver является BaseBlockDriver. Надеюсь, это прояснило мое замешательство., @SpaceMonkey55

класс SdSpiCard должен быть производным от BaseBlockDriver. но для AVR это потребляло память. поэтому автор решил исключить базовый класс для AVR. но затем везде в коде, где BaseBlockDriver использовался в качестве типа параметра, объект типа SdSpiCard не мог использоваться в качестве значения. Он решил эту проблему, создав макрос BlockDriver, который является BaseBlockDriver или SdSpiCard., @Juraj

Я думаю, что понял. К сожалению, для меня это пока неясно из-за непонимания ООП. Я приму ваш ответ, но, пожалуйста, уточните его и предоставьте дополнительную информацию, если вы найдете время. Спасибо за ваше терпение и вклад., @SpaceMonkey55

больше ничего нет. вы читали мой вопрос Биллу Грейману и его ответ на GitHub?, @Juraj

Да, я сделал. Ваш ответ не объясняет суть дела подробно, и я считаю, что его можно улучшить. Предполагается, что читатель хорошо разбирается в ООП. Я до сих пор не понимаю, как можно вызывать виртуальные методы. Т.е., когда BlockDriver является объектом BaseBlockDriver, каковы его фактические методы? Если мой BlockDriver указывает на объект BaseBlockDriver (что само по себе невозможно, поскольку это абстрактный класс), как будут вызываться его методы. вы говорите мне: «Объект **всегда** имеет тип SdSpiCard», тогда как определение типа, которое я цитировал в своем вопросе, ясно показывает, что это не так., @SpaceMonkey55

если класс BaseBlockDriver не исключен, это базовый класс для SdSpiCard. тип указателя на базовый класс может указывать на экземпляр производного класса. как будто вы можете называть какого-нибудь лабрадора «собакой»., @Juraj

Думаю, теперь у меня есть какое-то понимание по этому поводу. Спасибо, что терпели меня. Я приму этот ответ. Тем не менее, я все же чувствую, что ответ мог бы быть гораздо яснее., @SpaceMonkey55


1 ответ


Лучший ответ:

1

Определение типа в BlockDriver.h предназначено только для типа указателя, а не для экземпляра объекта. Объект всегда имеет тип SdSpiCard, но в одном случае он не является реализацией BlockDriverBase, поэтому параметры функции не могут ссылаться на него по базовому типу.

#if ENABLE_EXTENDED_TRANSFER_CLASS || ENABLE_SDIO_CLASS
class SdSpiCard : public BaseBlockDriver {
#else  // ENABLE_EXTENDED_TRANSFER_CLASS || ENABLE_SDIO_CLASS
class SdSpiCard {

использование typedef BlockDriver

class FatFileSystem : public  FatVolume {
 public:
  bool begin(BlockDriver* blockDev, uint8_t part = 0) {

Мне было любопытно, почему версия без BaseBlockDriver. Я спросил автора Билла Греймана, и он ответил:

Это связано с историей. Давным-давно использование виртуального базового класса стоило очень дорого. оперативной памяти и флэш-памяти, поэтому я делал это в основном для плат 328

,