Virtual datatype / enum

I need a virtual class:

class Configuration 
{
public:
    enum EPromptId;

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

      

So that each derived configuration can have its own set of 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:
};

      

This fails because each class needs to inject a virtual function with a Configuration :: EPromptId parameter (not Configuration1 :: EPromptId or Configuration2 :: EPromptId as in this code).

Is it possible for the base class to recognize the type of the parameter but define the values โ€‹โ€‹differently in each derived class (perhaps not using an enum, but keeping it strongly typed, i.e. not using int).

EDIT: I want two different configurations for two different applications. Queries can be stored in the db table, but each "application" will have its own table. A pointer to the base configuration class is contained in the class that interacts with some hardware (i.e. the actual mapping). Hardware is an io device that can be used to request and receive user input. When the hardware class is created, it will be passed a pointer to the correct configuration class and hence display the correct queries when requested.

+2


source to share


4 answers


First: you need an abstract class. (An abstract class is one that has at least one pure virtual function. The virtual base class is the class from which it is virtual

derived.)

Then: No, what you want is impossible. You cannot forward an ad enum

and define it later, let alone define it differently. And even if you could: what happens if someone goes epid_HappyBirthday

into Configuration2

who doesn't know about it?



I suggest that you explain to us what you want to do (instead of what you thought you found how it works), and maybe someone can come up with an idiom to solve your problem.

+3


source


You might be able to get most of what you want with templates ... until you hoped to store the collection Configuration*

and access them that way (you weren't, did you? Because you would need to know their types to know what to go through anyway ....)

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

      



then

enum EPromptId{
    epid_HappyBirthday
};

class Configuration1 : public Configuration< EPromptId >
{
public:
    CString getPrompt( EPromptId promptId ){
        return "";
    }
private:
};

      

+3


source


You cannot mix compilation type checking with runtime virtual function resolution.

You may have a common

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

      

and define two member functions in derivatives:

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:
};

      

If you want to ensure validity promptId

, you must check it manually at runtime in your child classes.

This approach is not suitable anyway, because to use a generic function, getPrompt()

you need to know which child class you are using in order to access it EPromptId

.

+1


source


My C ++ is a little rusty, but you can't do something like

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;

      

If you want to manage each id manually, just add a constructor and int
  EPromptId (int id) mId (id) {}

and change the initialization to

EPromptId configuration1::epid_HappyBirthday = 1;
EPromptId configuration1::epid_xxx = 5;

      

0


source







All Articles