виртуальный тип данных / enum - PullRequest
2 голосов
/ 28 августа 2009

Я хочу виртуальный класс, подобный этому:

class Configuration 
{
public:
    enum EPromptId;

    virtual CString getPrompt( EPromptId promptId ) = 0;
private:
};

Чтобы каждая производная конфигурация могла иметь свой собственный набор EPromptIds

 class Configuration1 : public Configuration
{
public:
    enum EPromptId{
        epid_HappyBirthday
    };

    CString getPrompt( EPromptId promptId ){
        return "";
    }
private:
};

class Configuration2 : public Configuration
{
public:
    enum EPromptId{
        epid_JummpingJehoshaphat
    };

    CString getPrompt( EPromptId promptId ){
        return "";
    }
private:
};

Это терпит неудачу, поскольку каждый класс должен внедрить виртуальную функцию с параметром Configuration :: EPromptId (не Configuration1 :: EPromptId или Configuration2 :: EPromptId, как в этом коде).

Можно ли заставить базовый класс распознавать тип параметра, но определять значения по-разному в каждом производном классе (возможно, не используя перечисления, но сохраняя его строго типизированным, т.е. не используя int).

РЕДАКТИРОВАТЬ: я хочу две разные конфигурации для двух разных «приложений». Приглашения могут храниться в таблице базы данных, но каждое «приложение» будет иметь свою собственную таблицу. Указатель на базовый класс конфигурации содержится в классе, который взаимодействует с некоторым оборудованием (т. Е. Который выполняет фактическое отображение). Аппаратное обеспечение представляет собой устройство ввода-вывода, которое можно использовать для запроса и получения пользовательского ввода. Когда класс оборудования создан, ему будет передан указатель на правильный класс конфигурации, поэтому при запросе отобразятся правильные подсказки.

Ответы [ 4 ]

3 голосов
/ 28 августа 2009

Возможно, вы сможете получить большую часть того, что вы хотите, с помощью шаблонов ... до тех пор, пока вы не надеетесь сохранить коллекцию Configuration* и получить к ней доступ таким образом (не так ли? Потому что вам нужно знать их типы, чтобы знать, что проходить в любом случае ....)

template< typename ENUM_TYPE >
class Configuration 
{
public:
    virtual CString getPrompt( ENUM_TYPE promptId ) = 0;
private:
};

тогда

enum EPromptId{
    epid_HappyBirthday
};

class Configuration1 : public Configuration< EPromptId >
{
public:
    CString getPrompt( EPromptId promptId ){
        return "";
    }
private:
};
3 голосов
/ 28 августа 2009

Первый: вам нужен класс abstract . (Абстрактный класс - это класс, который имеет хотя бы одну чисто виртуальную функцию. виртуальный базовый класс - это класс, *

производный от.) *1008*

Тогда: Нет, то, что вы хотите, невозможно. Вы не можете заранее объявить enum и определить его позже, не говоря уже о том, чтобы определить его по-другому. И даже если бы вы могли: что произойдет, если кто-то передаст epid_HappyBirthday на Configuration2, который не знает об этом?

Я предлагаю вам объяснить нам что вы хотите сделать (вместо того, как то, как вы думали, что нашли как сделать это работает), и, возможно, кто-то может придумать идиома, чтобы решить вашу проблему.

1 голос
/ 28 августа 2009

Вы не можете смешивать проверку типов во время компиляции с разрешением виртуальной функции во время выполнения.

Вы можете иметь общий

class Configuration 
{
public:
    virtual CString getPrompt( int promptId ) = 0;
private:
};

и определите две функции-члена в производных:

class Configuration1 : public Configuration
{
public:
    enum EPromptId{
        epid_HappyBirthday
    };

    CString getConfiguration1Prompt( EPromptId promptId ){
        return "";
    }
    virtual CString getPrompt( int promptId )
    {
      return getConfiguration1Prompt(static_cast<EPromptId>(promptId));
    } 
private:
};

class Configuration2 : public Configuration
{
public:
    enum EPromptId{
        epid_JummpingJehoshaphat
    };

    CString getConfiguration2Prompt( EPromptId promptId ){
        return "";
    }
    virtual CString getPrompt( int promptId )
    {
      return getConfiguration2Prompt(static_cast<EPromptId>(promptId));
    } 
private:
};

Если вы хотите убедиться в правильности promptId, вы должны проверить его вручную во время выполнения в дочерних классах.

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

0 голосов
/ 28 августа 2009

Мой c ++ немного ржавый, но вы не можете сделать что-то вроде

struct EPromptId {
    EPromptId() mId(sId++) { }
    operator int() { return mId; }
    friend static bool operator==(EPromptId lhs, EPromptId rhs) { 
        return lhs.mId == rhs.mId;
    }
private:
    int mId;
    static int sId;
};

struct configuration1 {
    static const EPromptId epid_HappyBirthday;
    static const EPromptId epid_xxx;

    CString getPrompt(EPromptId promptId ){
        if (promptId == epid_HappyBirthday)
            return "";
        else if (promptId == epid_xxx)
    }
}

// somewhere else
EPromptId configuration1::epid_HappyBirthday;
EPromptId configuration1::epid_xxx;

Если вы хотите управлять каждым идентификатором вручную, просто добавьте конструктор a и int
EPromptId (int id) mId (id) {} ​​

и измените инициализацию на

EPromptId configuration1::epid_HappyBirthday = 1;
EPromptId configuration1::epid_xxx = 5;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...