C ++ Dynamic Dispatch без виртуальных функций

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

12
задан Kristopher Johnson 28 August 2013 в 16:49
поделиться