У меня есть устаревший код, который вместо виртуальных функций использует поле kind
для динамической отправки. Это выглядит примерно так:
// Base struct shared by all subtypes
// Plain-old data; can't use virtual functions
struct POD
{
int kind;
int GetFoo();
int GetBar();
int GetBaz();
int GetXyzzy();
};
enum Kind { Kind_Derived1, Kind_Derived2, Kind_Derived3 /* , ... */ };
struct Derived1: POD
{
Derived1(): kind(Kind_Derived1) {}
int GetFoo();
int GetBar();
int GetBaz();
int GetXyzzy();
// ... plus other type-specific data and function members ...
};
struct Derived2: POD
{
Derived2(): kind(Kind_Derived2) {}
int GetFoo();
int GetBar();
int GetBaz();
int GetXyzzy();
// ... plus other type-specific data and function members ...
};
struct Derived3: POD
{
Derived3(): kind(Kind_Derived3) {}
int GetFoo();
int GetBar();
int GetBaz();
int GetXyzzy();
// ... plus other type-specific data and function members ...
};
// ... and so on for other derived classes ...
а затем члены функции класса POD
реализованы следующим образом:
int POD::GetFoo()
{
// Call kind-specific function
switch (kind)
{
case Kind_Derived1:
{
Derived1 *pDerived1 = static_cast<Derived1*>(this);
return pDerived1->GetFoo();
}
case Kind_Derived2:
{
Derived2 *pDerived2 = static_cast<Derived2*>(this);
return pDerived2->GetFoo();
}
case Kind_Derived3:
{
Derived3 *pDerived3 = static_cast<Derived3*>(this);
return pDerived3->GetFoo();
}
// ... and so on for other derived classes ...
default:
throw UnknownKindException(kind, "GetFoo");
}
}
POD::GetBar()
, POD::GetBaz()
, POD::GetXyzzy()
, и другие члены реализованы аналогично.
Этот пример упрощен. Фактический код имеет около десятка разных подтипов POD
и несколько десятков методов. Новые подтипы POD
и новые методы добавляются довольно часто, поэтому каждый раз, когда мы это делаем, мы должны обновлять все эти операторы switch
.
Типичным способом обработки этого было бы объявить членов функции virtual
в классе POD
, но мы не можем этого сделать, потому что объекты находятся в общей памяти. Существует много кода, который зависит от того, какие эти структуры являются обычными данными, поэтому, даже если бы я мог найти способ иметь виртуальные функции в объектах с общей памятью, я бы не хотел этого делать.
Итак, я ищу предложения о том, как наилучшим образом очистить это, чтобы все знания о том, как вызвать методы подтипа, централизованы в одном месте, а не разбросаны между несколькими дюжинами switch
операторов в пара дюжины функций.
Что происходит со мной, так это то, что я могу создать какой-то класс адаптера, который обертывает POD
и использует шаблоны для минимизации избыточности. Но прежде чем я начну с этого пути, я хотел бы знать, как другие справились с этим.