oop — альтернатива виртуальным статическим функциям в c ++?

В заголовочном файле .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?

1

Решение

Вызов виртуальной функции без объекта является противоречием,
так как разрешение зависит от типа объекта.
случаи, когда вам может понадобиться вызвать одну и ту же функцию
зависит от типа объекта или указание класса
явно, без объекта. Это легко сделать с помощью
две функции, одна статическая и одна виртуальная. (Как правило,
виртуальный просто перешлет в статику.)

РЕДАКТИРОВАТЬ:

Простой пример (из реального кода):

#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() ) ...

(Мы установили правило, что единственный способ получить
имя класса было с помощью одной из этих функций. Тот
эффективно усвоил имена классов, и позволил
простые сравнения указателей для работы. В системах мы были
работая над этим, это было важно.)

4

Другие решения

Вы можете сделать это немного хакерски =)

//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: очень странно, что вы не хотите объявлять эту функцию в производных классах, потому что когда вы используете виртуальные функции, вы должны объявлять их в производном классе

1

Одна возможность — определить их только в производных классах:

  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 или тип-черты для альтернативных подходов.

1
По вопросам рекламы [email protected]