C++: как специализация шаблонов работает для иерархий классов шаблонов?C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 C++: как специализация шаблонов работает для иерархий классов шаблонов?

Сообщение Anonymous »

Ниже у меня есть две отдельные шаблонные иерархии классов ( -> CheckingAccount и Logger -> ConsoleLogger) и класс шаблона Bank, который использует оба.
цель состоит в том, чтобы использовать разные Logger: один для фундаментальных типов, таких как long, и другой, адаптированный для объектов Account, причем последний принимает аргумент-указатель из-за полиморфизма Account .
Полагаю, этого можно было бы достичь полностью с помощью шаблонов, однако решение этой проблемы должно пролить некоторый свет на то, как специализация шаблонов работает для иерархий наследования классов, если вообще работает.
Приведенный ниже MWE не компилируется успешно, см. ссылку на компилятор.

Код: Выделить всё

#include 
//#include 
//#include 

class Account {
public:
virtual ~Account() {}

virtual const long getId() = 0;
};

class CheckingAccount: public Account {
public:
CheckingAccount() = default;
CheckingAccount(const long id): _id{id} {}
~CheckingAccount() {}

const long getId() {
return _id;
}

private:
long _id;
};

////////////////////////////////////////////////////////////////
template class Logger {
public:
virtual void logTransfer(T, T, const double) = 0;
};

template class ConsoleLogger : public Logger {
public:
void logTransfer(T from, T to, const double amount) override {
printf("[console] %ld -> %ld: %f\n", from, to, amount);
}
};

// template class specialization
template class ConsoleLogger : public Logger {
public:
void logTransfer(Account* from, Account* to, const double amount) override {
printf("[console] %ld -> %ld: %f\n", from->getId(), to->getId(), amount);
}
};

////////////////////////////////////////////////////////////////////
template struct Bank {
void setLogger(Logger* new_logger) {
logger = new_logger;
}

void logTransfer(T from, T to, const double amount) {
if(logger)
logger->logTransfer(from, to, amount);
}

private:
Logger* logger;
};

// template class specialization
template struct Bank {
void setLogger(Logger* new_logger) {
logger = new_logger;
}

void logTransfer(Account* from, Account* to, const double amount) {
if(logger)
logger->logTransfer(from, to, amount);
}

private:
Logger* logger;
};

/////////////////////////////////////////////
int main() {
// try with long input
ConsoleLogger console_logger;
Bank bank;
bank.setLogger(&console_logger);
bank.logTransfer(500L, 1000L, 23.56);

// try with Account input
CheckingAccount* a = new CheckingAccount{500};
CheckingAccount* b = new CheckingAccount{1000};
printf("Account no.%ld\n", a->getId());
printf("Account no.%ld\n", b->getId());
ConsoleLogger console_logger2;
Bank bank2;
bank2.setLogger(&console_logger2);
bank2.logTransfer(a, b, 42.81);
delete a;
delete b;
}

Выходы компилятора:

Код: Выделить всё

main.cpp: In function ‘int main()’:
main.cpp:94:19: error: cannot convert ‘ConsoleLogger*’ to ‘Logger*’
94 |   bank2.setLogger(&console_logger2);
|                   ^~~~~~~~~~~~~~~~
|                   |
|                   ConsoleLogger*
main.cpp:65:36: note:   initializing argument 1 of ‘void Bank::setLogger(Logger*)’
65 |   void setLogger(Logger* new_logger) {
|                  ~~~~~~~~~~~~~~~~~~^~~~~~~~~~
main.cpp: In instantiation of ‘void ConsoleLogger::logTransfer(T, T, double) [with T = CheckingAccount*]’:
main.cpp:35:8:   required from here
main.cpp:36:27: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 2 has type ‘CheckingAccount*’ [-Wformat=]
36 |       printf("[console] %ld -> %ld: %f\n", from, to, amount);
|                         ~~^                ~~~~
|                           |                |
|                           long int         CheckingAccount*
Короче говоря, компилятор не видит специализацию шаблона для ConsoleLogger.
Я пытался специализировать Logger непосредственно из Logger и получить от него ConsoleLogger, но получил то же сообщение об ошибке от компилятора.

Подробнее здесь: https://stackoverflow.com/questions/793 ... te-classes
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»