Radu Chivu
Radu Chivu

Reputation: 1065

c++ defining object type via enum

I have this basic setup:

enum{
    BASE,
    PRIMITIVE,
    ...
};

class IUnknown{
public:
    bool inline is(int type){return inv_type == type;}
private:
    enum {inv_type = BASE};
};

class Primitive: public IUnkown{
private:
    enum {inv_type = PRIMITIVE};
};

My problem is that I would want to be able to call is on a Primitive instance and have it return true when type is equal to the value in the enum I have declared in the Primitive class.

The only solution I have found is to declare the 'is' function as virtual and have a copy in every subclass, but I wondered if it would be possible to somehow redefine the enum and have the is function in IUnkown take the value from there

Upvotes: 0

Views: 1756

Answers (3)

Andrei
Andrei

Reputation: 5005

Why not go all out and use strings instead of enums.

const char * baseStr = "base";
const char * derived1Str = "derived1";
const char * derived2Str = "derived2";

class base
{
public:
    virtual bool is(const char * str)
    {
        return strcmp(baseStr, str) ? false : true;
    }
};

class derived1 : public base
{
public:
    bool is(const char * str)
    {
        if ( strcmp(derived1Str, str) )
            return base::iA(str);

        return true;
    }
};

class derived2 : public derived1
{
public:
    bool is(const char * str)
    {
        if ( strcmp(derived2Str, str) )
            return derived1::is(str);

        return true;
    }
};

This has the benefit that this

base * b = new derived2();
bool is = b->isA(baseStr);

sets is to true.

Upvotes: 0

Seth Carnegie
Seth Carnegie

Reputation: 75130

enums by themselves don't take up storage space because they're just lists of acceptable values for an enum variable. You have to have some runtime storage going on for a virtual function to actually work with the runtime type of the object. I would just use an int or something:

enum{
    BASE,
    PRIMITIVE,
    ...
};

class IUnknown{
public:
    bool is(int type) const {return inv_type == type;}

protected:
    IUnknown(int type) : inv_type(type) { }

private:
    const int inv_type;
};

class Primitive: public IUnkown{
private:
    Primitive() : IUnknown(PRIMITIVE) { }
};

Upvotes: 1

John Zwinck
John Zwinck

Reputation: 249123

You could have your IUnknown class define a protected constructor (which would then have to be called from each derived class). It would take one of the enum values and store it. The stored value would then be compared against in the is() method.

If you don't like this, and prefer to add a virtual is() method to IUnknown, but don't want to have to define it in every derived class, you could do this:

template <int Tinv_type>
class IUnknownT : public IUnknown{
public:
    virtual bool is(int type){return inv_type == type;}
protected:
    enum {inv_type = Tinv_type};
};

class Primitive: public IUnknownT<PRIMITIVE>{
};

Upvotes: 1

Related Questions