Мне интересно написать принтер для вывода в двух разных форматах. Назовем их txt и csv. Можно ли реализовать на C ++ что-то подобное ниже? класс принтера {общедоступный: виртуальный пустой заголовок () = 0; }; ...

0
Laurenţiu Terţan 8 Апр 2021 в 21:48

4 ответа

Лучший ответ

Вместо auto вам нужен указатель на базовый класс

int decider(int type) {
  Printer* prt;
  if (type == 1) {
     prt = new CSV;
  } else {
     prt = new TXT;
  }
  prt->header();
}

Но вместо необработанных указателей и new (поскольку вы теряете память из-за отсутствующего delete) я бы вместо этого использовал здесь умные указатели

#include <memory>

int decider(int type) {
  std::unique_ptr<Printer> prt;
  if (type == 1) {
     prt = std::make_unique<CSV>();
  } else {
     prt = std::make_unique<TXT>();
  }
  prt->header();
}

Как отметил @FredLarson, вам также понадобится виртуальный деструктор в вашем базовом классе

class Printer {
public:
  virtual ~Printer() = default;
  virtual void header() = 0;
};

Вы также должны публично наследовать от базового класса

class CSV : public Printer { 
  ...
};

class TXT : public Printer {
  ...
};
4
Cory Kramer 8 Апр 2021 в 19:51

Это правильный путь:

void decider(int type) {
  std::unique_ptr<Printer> prt{};
  if (type == 1) {
     prt = std::make_unique<CSV>();
  } else {
     prt = std::make_unique<TXT>();
  }
  prt->header();
}
2
Nathan Xabedi 8 Апр 2021 в 18:54

Да, такой полиморфизм возможен. Вот пример, основанный на вашем:

#include <stdio.h>

class Printer {
public:
  virtual void header() {};
};

class CSV : public Printer {
public:
 void header() { printf("csv\n"); }
};

class TXT : public Printer {
public:
 void header() { printf("txt\n"); }
};

int decider(int type) {
  Printer* prt;
  if (type == 1) {
     prt = new CSV();
  } else {
     prt = new TXT();
  }
  prt->header();
}

int main() {

    int type = 1;

    decider(type);

    type = 0;

    decider(type);
}
2
Leo Lamas 8 Апр 2021 в 19:02

А как насчет передачи требуемого типа в качестве параметра шаблона?

Я имею в виду что-то как

template <typename T>
void decider ()
 {
   auto prt = new T;
   prt.header();

   delete prt;
 }

Что вы можете назвать следующим образом

decider<CSV>();
decider<TXT>();

Как указал Дэниел Х (спасибо!), Это работает, только если вы знаете тип времени компиляции; если тип (CSV или TXT) определяется временем выполнения, это решение неосуществимо.

0
max66 8 Апр 2021 в 19:00