#c #polymorphism
#c #полиморфизм
Вопрос:
Я должен разработать библиотеку с использованием C , и ниже приведены мои требования.
- Пользователи должны иметь возможность расширять методы моего класса API
- Виртуальные методы, реализованные пользователем, будут вызываться внутри библиотеки полиморфно
- Я должен помещать две записи журнала до и после каждого вызова виртуального метода
- Когда пользователь создает свои собственные классы и виртуальные методы, И если он / она использует мою библиотеку (имеет ссылку на), в дополнение к обычной динамической привязке, вышеуказанный пункт 3 (имеющий две записи журнала) должен быть удовлетворен
Идея может быть изложена в общих чертах следующим образом?
class BaseClass
{
public:
virtual void foo() = 0;
};
Пользовательская реализация была бы похожа
class DerivedClass: public BaseClass
{
public:
virtual void foo() {/*come impl*/}
};
Используя следующий код,
BaseClass * bp = new DerivedClass();
bp->foo();
Должно быть эквивалентно чему-то вроде,
BaseClass * bp = new DerivedClass();
log_start(typeid(*bp).name());
bp->foo();
log_end(typeid(*bp).name());
Но я не могу попросить пользователей моей библиотеки (и даже я не могу делать это везде) размещать эти материалы для ведения журнала всякий раз, когда они используют мой API. Поскольку существует множество виртуальных функций и их использование, я не могу поместить ведение журнала везде в моей библиотеке.
Есть ли какой-нибудь простой способ добиться этого? Нужно ли мне создавать свою собственную виртуальную таблицу?
Ответ №1:
Вместо того, чтобы вызывать их foo
напрямую, вы могли бы использовать пользовательскую реализацию foo
, но вместо этого вызывать bar
. bar
завершил бы вызов на foo
, как в:
class BaseClass {
public:
void bar() {
log_start(typeid(*this).name());
foo();
log_end(typeid(*this).name());
}
protected:
virtual void foo() = 0;
};
Использование было бы:
BaseClass * bp = new DerivedClass();
bp->bar();
Ответ №2:
Для этого случая вам следует использовать что-то вроде шаблона Template Method шаблон
class BaseClass
{
public:
void foo() {
log_start(typeid(*this).name());
doFoo();
log_end(typeid(*this).name());
}
protected:
virtual void doFoo() = 0;
};
class DerivedClass: public BaseClass
{
protected: // or private, depends on use case
virtual void doFoo() {/* some impl */}
};
int main() {
BaseClass * bp = new DerivedClass();
bp->foo();
delete bp;
return 0;
}
Смотрите рабочий пример здесь.
Комментарии:
1. Спасибо, хорошая техника