简体   繁体   中英

Enum & class member function with the same name

In the particular coding standard being enforced at my workplace, accessor methods in a class follow a specific naming convention. For any given member variable, the getter is the same name, and the setter is prefixed with Set . See example below.

class Foo
{
public:
    int Number() const { return m_number; }
    void SetNumber(int number) { m_number = number; }

private:
    int m_number;
};

This becomes quirky when I have an enum with the same name:

enum class Number
{
    One, Two, Three
};

class Foo
{
public:
    Number Number() const { return m_number; }
    void SetNumber(Number number) { m_number = number; }

private:
    Number m_number;
};

The above example will not compile because in some places, the compiler can't determine if I'm referring to the enum name or the function name. So to fix this without violating the coding standard, I would have to use :: in places of ambiguity and I'm actually referring to the enum:

enum class Number
{
    One, Two, Three
};

class Foo
{
public:
    ::Number Number() const { return m_number; }
    void SetNumber(::Number number) { m_number = number; }

    void DoStuffWithNumber()
    {
        if (m_number == ::Number::One)
        {
            // Do stuff
        }
    }

private:
    Number m_number;
};

This is a little confusing for readers of the code, but also a bit annoying to have to fully qualify the enumeration name in certain contexts. It's not straightforward all the time.

What's a more reasonable workaround here? Obviously I could do something like rename the accessor to GetNumber() , but I'm curious to see what other solutions people can come up with.

You could add enum prefix to explicitly refer to enum class name, not function name.

enum class Number
{
    One, Two, Three
};

class Foo
{
public:
    enum Number Number() const { return m_number; }
    void SetNumber(enum Number number) { m_number = number; }

private:
    enum Number m_number; // Number here refers to enum class, not function
};

Note: Above code works under g++, but has problem in Visual Studio. VS seems not working well with scoped enumerations. We can use unscoped enumerations (without class keyword) instead.

Since enum can take a range of values I would use plural here:

enum class Numbers
//               ^
{
    One, Two, Three
};

This is not an uncommon practice. Eg, in Google C++ style guide they use the following enums naming example:

enum UrlTableErrors {
  kOK = 0,
  kErrorOutOfMemory,
  kErrorMalformedInput,
};
enum AlternateUrlTableErrors {
  OK = 0,
  OUT_OF_MEMORY = 1,
  MALFORMED_INPUT = 2,
};

I personally prefer to start member functions with lower case letters and only static (member) functions with upper case letters. In case there is a real getter and setter function I would also prefer to mark them as pair like setNumber and getNumber .

This alone would make the code look like this:

enum class Number
{
    One, Two, Three
};

class Foo
{
public:
    Number getNumber() const { return m_number; }
    void setNumber(Number number) { m_number = number; }
private:
    Number m_number;
};

For the case of a accessing m_number via a function only named number I would return a reference (or const reference in the const case):

enum class Number
{
    One, Two, Three
};

class Foo
{
public:
    Number& number() { return m_number; }
    const Number& number() const { return m_number; }
private:
    Number m_number;
};

In this case you might want to get rid of the "named function" at all and just provide conversation operators.

Why not use a prefix for your Enum? Much like you use m_ for member variables, you could prefix your enums with an E:

enum class ENumber
{
    One, Two, Three
};

This way it also helps you quickly identify that you're dealing with an enum here, and not a class or function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM