Хобрук: Ваш путь к мастерству в программировании

Как передать производные классы абстрактного класса в качестве параметра?

В настоящее время я работаю над заголовком С++ для кодирования и декодирования текста. Если быть точным: UTF-8, UTF-16, UCS-2 и UTF-32. Но я дошел до того, что мои знания C++ больше не помогут:

Я хотел бы использовать абстрактный класс для декодирования и кодирования, создавая базовые классы для каждого кодека. Затем, при использовании любой функции, связанной с кодированием или декодированием, разработчик должен иметь возможность просто передать функции пользовательский тип данных.

Проблема в том, что я понятия не имею, как это сделать на самом деле. В конце концов, вы не можете передать статический класс в качестве параметра. Но я также не хочу ничего жестко кодировать; разработчик также должен иметь возможность добавлять любой кодек без особых проблем и без изменения моего заголовка.

Кроме того, он должен быть максимально легким. Код будет выглядеть примерно так:

namespace Encoding {

  class Encoder {
  public:
    virtual std::string Encode(std::string sOriginal) = 0;
  };

  // Derived classes like UTF8 and UCS2 here

}

void OutputEncoded(std::string s, Encoder enc) {
  std::cout << enc.Encode(s);
}


int main() {
  OutputEncoded("Hellö Wörld!", Encoding::UTF8);
}

есть идеи как это сделать? Может быть, способ без создания объекта, а только со статическими методами? Или мне нужно использовать объект с указателем?


  • что такое статический класс? 23.04.2020
  • вы пришли из С#, может быть? C++ не имеет статических классов, единственное, что я нашел, это это вопрос откуда из кода ОП можно было узнать что они означают. Может быть, если вы включите какой-то код, это также возможно здесь 23.04.2020
  • Пожалуйста, включите минимально воспроизводимый пример кода, который вы хотели бы написать, независимо от того, насколько он сломан, это поможет объяснить 23.04.2020
  • Возможно ли, что вы используете static для обозначения не абстрактного? 23.04.2020
  • Я буду игнорировать использование слова static здесь, потому что это не помогает. Учитывая это, я бы посоветовал вам поискать шаблон абстрактной фабрики. Это звучит близко к тому, что вы хотите. 23.04.2020
  • @idclev463035818 Теперь я в замешательстве ???? Что он делает, когда я пишу статический класс XYZ {};? Потому что это компилируется и запускается. Под статическим я подразумеваю то, что вы не можете создавать из него какие-либо объекты. Потому что зачем создавать объект кодировщика/декодера? В конце концов, внутри есть только статические методы. 23.04.2020
  • static class XYZ {}; — синтаксическая ошибка (класс хранения можно указать только для объектов и функций). В С++ нет имени для классов только со статическими методами, потому что в С++ от них мало пользы, обычно предпочтительны свободные функции в пространстве имен. Также наличие только статических методов не мешает вам создавать экземпляр 23.04.2020
  • Кстати, поэтому я попросил вас показать код, на самом деле все помогает избежать такого недоразумения. Теперь мне любопытно, как вы можете заставить static class XYZ {}; компилироваться без ошибок 23.04.2020
  • О, тогда ладно. (Но все же; по крайней мере, в VS он не выдает никаких ошибок) Я сам нашел ответ, сейчас отредактирую вопрос, чтобы он больше не содержал слова «статический», и сам на него отвечу. Тем не менее, спасибо idclev463035818 и Андре. 23.04.2020
  • Вот мой код: pastebin.com/2JNURgR6 23.04.2020
  • Комментарий — не лучшее место для написания кода. (если применимо) отредактируйте свой вопрос (или ответ), у них лучшее форматирование. 23.04.2020
  • Я понимаю. Чем больше вы знаете ;) Думаю, теперь лучше. 23.04.2020
  • Есть некоторые онлайн-среды разработки, более подходящие, чем pastebin. 23.04.2020

Ответы:


1

Я сам нашел способ. На самом деле довольно просто.

class Base {
public:
  virtual void DoSomething(void) = 0;
};

class Derived : public Base {
  void DoSomething(void) {
    std::cout << "Test";
  }
} DerivedTest;

Base* const DerivedTestPtr = &DerivedTest;



void Test(Base* b) {
  b->DoSomething();
}



int main() {
  Test(DerivedTestPtr);
}
23.04.2020
  • Вы можете даже не использовать глобальную переменную; int main() { Derived d; Test(&d); } Передача по ссылке более уместна, чем по указателю, поскольку nullptr является неправильным вводом. 23.04.2020
  • вы также можете уточнить свой вопрос, потому что без кода из ссылки в вашем комментарии не совсем понятно, на какой вопрос он отвечает. Я бы добавил код и сообщение об ошибке, тогда это был бы хороший ответ, я думаю 23.04.2020
  • @ Jarod42 Смысл в том, чтобы сделать это как можно проще. Строка кода должна выглядеть как EncodeString(Hello wörld, UTF8); 23.04.2020
  • @RobinLe, но если ваш исходный код уже был в порядке, то в чем был вопрос? 23.04.2020
  • Как это сделать ПРАВИЛЬНО. Мне он показался слишком быстрым и грязным. Я думал, что будет лучший способ, может быть, даже более эффективный. 23.04.2020
  • спасибо за серьезную попытку исправить вопрос +1 23.04.2020
  • @ idclev463035818 Извините, что я слишком расплывчат. Я все еще новичок как в C++, так и в StackOverflow (хотя я пишу код на C++ более 1,5 лет). 23.04.2020

  • 2

    Возможной альтернативой абстрактному классу является шаблон:

    namespace Encoding {
    
      class UTF8 {
      public:
        static std::string Encode(std::string sOriginal);
      };
      class UCS2 {
      public:
        static std::string Encode(std::string sOriginal);
      };
    
    }
    
    template <typename Encoder>
    void OutputEncoded(const std::string& s) {
      std::cout << Encoder::Encode(s);
    }
    
    int main()
    {
      OutputEncoded<Encoding::UTF8>("Hellö Wörld!");
    }
    

    Классы UTF8 и UCS2 должны учитывать совместимый/одинаковый интерфейс без принудительного исполнения, обеспечиваемого абстрактным классом и виртуальным методом.

    Концепция C++20 может помочь обеспечить правильное использование. Раньше можно было использовать SFINAE, но более подробный.

    23.04.2020
    Новые материалы

    Прогресс в технологии Трансформеров часть 3
    Многомасштабный управляющий сигнальный преобразователь для бесфазного синтеза движения (arXiv) Автор: Линтао Ван , Кун Ху , Лей Бай , Юй Дин , Ваньли Оуян , Чжиюн Ван . Аннотация:..

    Представляем поддержку компонентов Vue.js. Мгновенный HMR и многое другое.
    Хотя у FuseBox уже был плагин Vue, он был базовым и не имел многих функций, которые делали работу с Vue.js такой приятной. Однако с этим выпуском мы рады сообщить, что в FuseBox..

    Приключения в Javascript, часть 1
    Я продолжаю думать о том, чтобы писать больше, но чем больше я думаю об этом, тем меньше я это делаю. Итак, сегодня я перестал думать и начал писать. Отсюда можно только спускаться… В..

    Понимание дженериков в TypeScript: подробное руководство
    Введение TypeScript, строго типизированный надмножество JavaScript, хорошо известен своей способностью улучшать масштабируемость, удобочитаемость и ремонтопригодность приложений. Одной из..

    Учебные заметки JavaScript Object Oriented Labs
    Вот моя седьмая неделя обучения программированию. После ruby ​​и его фреймворка rails я начал изучать самый популярный язык интерфейса — javascript. В отличие от ruby, javascript — это более..

    Разбор строк запроса в vue.js
    Иногда вам нужно получить данные из строк запроса, в этой статье показано, как это сделать. В жизни каждого дизайнера/разработчика наступает момент, когда им необходимо беспрепятственно..

    Предсказание моей следующей любимой книги 📚 Благодаря данным Goodreads и машинному обучению 👨‍💻
    «Если вы не любите читать, значит, вы не нашли нужную книгу». - J.K. Роулинг Эта статья сильно отличается от тех, к которым вы, возможно, привыкли . Мне очень понравилось поработать над..