В заголовочном файле .hpp:
class Base{
public:
static /*Some Return Type*/ func(/*Some Datatype*/);
}
class Derived1 public Base{
public:
Derived1();
~Derived1();
}
class Derived1 public Base{
public:
Derived2();
~Derived2();
}
В файле cpp .cpp:
/*Some Return Type*/ Derived1::func(/*Some Datatype*/){
}
/*Some Return Type*/ Derived2::func(/*Some Datatype*/){
}
Это, очевидно, терпит неудачу, потому что нет способа переопределить статический метод в подклассе. Но как получить вышеуказанный функционал?
Для меня обязательно назвать что-то вроде этого:
/*Some Return Type*/ result = Derived1::func(/*Some Datatype*/)
/*Some Return Type*/ result = Derived2::func(/*Some Datatype*/)
Я знаю, что абстрактный метод можно определить в базовом классе, как показано ниже, а затем определить их в классе Derived:
В заголовочном файле .hpp:
class Base{
public:
virtual /*Some Return Type*/ func(/*Some Datatype*/) const = 0;
}
Но проблема в том, что виртуальные методы требуют создания объекта, а это не так. Я хочу вызвать метод без создания объекта. Если бы были разрешены виртуальные статические методы, они бы послужили цели.
Единственная альтернатива, о которой я могу подумать, — объявить функцию func()
во всех производных классах в заголовочном файле и удалите его из базового класса. Есть ли альтернативный способ сделать это? Так что объявление только один раз в Базовом классе, и все производные классы должны только определить их, а не redeclare?
Вызов виртуальной функции без объекта является противоречием,
так как разрешение зависит от типа объекта.
случаи, когда вам может понадобиться вызвать одну и ту же функцию
зависит от типа объекта или указание класса
явно, без объекта. Это легко сделать с помощью
две функции, одна статическая и одна виртуальная. (Как правило,
виртуальный просто перешлет в статику.)
Простой пример (из реального кода):
#define DECLARE_CLASS_NAME(className) \
static char className() { return STRINGIZE(className); } \
virtual char* getClassName() { return className(); }
class Base
{
public:
DECLARE_CLASS_NAME(Base);
// ...
};
class Derived : public Base
{
public:
DECLARE_CLASS_NAME(Derived);
// ...
};
и так далее, во всех производных классах. Это было использовано для
получить имена типов для сериализации, например:
std::string typeName = pObj->getClassName();
а также как примитивный RTTI (это было около 20 лет назад):
if ( pObj->getClassName() == Derived::className() ) ...
(Мы установили правило, что единственный способ получить
имя класса было с помощью одной из этих функций. Тот
эффективно усвоил имена классов, и позволил
простые сравнения указателей для работы. В системах мы были
работая над этим, это было важно.)
Вы можете сделать это немного хакерски =)
//header file
template<class T>
struct base_t
{
static void do_smth();
};
struct derived1_t : base_t<derived1_t>
{
};
struct derived2_t : base_t<derived2_t>
{
};
//cpp file
void base_t<derived1_t>::do_smth() // `note base_t<derived1_t>::` instead of `derived1_t::`
{
std::cout << "aaa" << std::endl;
}
PS: очень странно, что вы не хотите объявлять эту функцию в производных классах, потому что когда вы используете виртуальные функции, вы должны объявлять их в производном классе
Одна возможность — определить их только в производных классах:
struct Base
{
// nothing
};
struct Derived1 : public Base
{
static void func() { /*...*/ }
};
struct Derived2 : public Base
{
static void func() { /*...*/ }
};
Это позволяет вам звонить:
Derived1::foo();
Derived2::foo();
Вызов его для базового типа и ожидание компилятора, чтобы выяснить, какой подтип вы имеете в виду не могу Работа:
// How will the compiler know to choose
// between Derived1:: func or Derived2:: func ?
Base::func();
Возможно, вы захотите взглянуть на CRTP или тип-черты для альтернативных подходов.