Обновленный ответ :
Похоже, что вы хотите, на самом деле это шаблон фабрики. Я собираюсь использовать ведение журнала в качестве примера, где я предполагаю, что в одной конфигурации вы хотите войти, а в другой вы можете не захотеть:
// logger_interface.h
class LoggerInterface {
public:
virtual ~LoggerInterface() {}
virtual void Log(const string& message) = 0;
protected:
LoggerInterface() {}
};
Первым шагом является создание чисто виртуального интерфейса, представляющего поведение, которое настраивается, как в примере выше. Затем мы создадим фабричную функцию, которая может создать функцию на основе конфигурации:
// logger_factory.h
LoggerInterface* CreateLogger(LoggerOptions options);
При реализации фабрики мы скрываем различные реализации:
// logger_factory.cc
class DoNotLogLogger : public LoggerInterface {
public:
DoNotLogLogger() {}
virtual ~DoNotLogLogger() {}
virtual void Log(const string& message) {}
};
class LogToStdErrLogger : public LoggerInterface {
public:
LogToStdErrLogger() {}
virtual ~LogToStdErrLogger() {}
virtual void Log(const string& message) {
std::cout << message << std::endl;
}
};
LoggerInterface* CreateLogger(LoggerOptions options) {
if (options.IsLoggingEnabled() && options.ShouldLogToStdErr()) {
return new LogToStdErrLogger;
}
return new DoNotLogLogger;
}
Нет причины, по которой объект, который вы динамически создаете таким образом, должен быть глобальным; на самом деле, сделать его глобальным - очень плохая идея. Просто создайте его там, где вам нужно, и передайте его в качестве параметра нужным функциям.
Оригинальный ответ :
Наследование не то слово, которое вы ищете. По сути, вы запрашиваете static function:
class ClassName {
public:
static void methodName();
};
В приведенном выше примере methodName
можно вызвать с помощью ClassName::methodName()
, не требуя конкретного экземпляра класса с именем ClassName
. Тем не менее, если вы хотите сделать это, это больше согласуется с соглашениями стиля C ++, чтобы сделать его автономной функцией в пространстве имен, например:
namespace name_of_namespace {
void functionName();
}
Вышеуказанное вызывается с использованием name_of_namespace::functionName()
, как в предыдущем примере, за исключением того, что префикс легче изменить или удалить (например, с помощью директивы using).
ПРИМЕЧАНИЕ: с точки зрения проектирования, вы должны использовать отдельно стоящую или статическую функцию, только если она не зависит от какого-либо состояния (кроме переданных ей параметров) и нет возможности альтернативных реализаций. Как только есть состояние или альтернативные реализации, вы действительно должны передать объект, инкапсулирующий это состояние, даже если это трудная задача, поскольку передача объекта облегчает его настройку, облегчает макетирование в тестах. и позволяет избежать проблем с многопоточностью.