2017-01-24 13 views
1

В конкретном стандарте кодирования, который применяется на моем рабочем месте, методы доступа в классе следуют конкретному соглашению об именах. Для любой заданной переменной-члена геттер имеет одно и то же имя, а сеттер имеет префикс Set. См. Пример ниже.Функция Enum & class member с тем же именем

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

private: 
    int m_number; 
}; 

Это становится изворотливым, когда у меня есть перечисление с тем же именем:

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

Приведенный выше пример не будет компилировать, потому что в некоторых местах, компилятор не может определить, если я имею в виду имя перечисления или имя функции. Таким образом, чтобы исправить это, не нарушая стандарт кодирования, я бы использовать :: в местах неоднозначности, и я на самом деле со ссылкой на перечисление:

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

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

Что является более разумным обходным решением здесь? Очевидно, я мог бы сделать что-то вроде переименования аксессора на GetNumber(), но мне любопытно узнать, какие другие решения могут придумать.

+0

Ну, вы не можете изменить имя получателя, можете ли вы? это стандарт кодирования на рабочем месте. Итак, как насчет того, чтобы имя перечисления было множественным? –

+1

Как вы относитесь к созданию буровой установки и простому оператору преобразования ('operator Number() {return m_number;}')? – NathanOliver

+0

@NathanOliver Это менее интуитивно понятно, ИМХО. Личные предпочтения - избегать операторов, если я не реализую что-то с семантикой, которые очевидны и четко определены (операции копирования/перемещения, потоки, арифметические типы и т. Д.). –

ответ

2

Вы можете добавить префикс enum, чтобы явно ссылаться на имя класса перечисления, а не на имя функции.

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

Примечание: Приведенный выше код работает под г ++, но есть проблема в Visual Studio. Кажется, что VS не работает с облачными перечислениями. Вместо этого мы можем использовать подсчеты без пробелов (без ключевого слова class).

+1

Похоже, что это не работает в тех случаях, когда вам действительно нужно обратиться к одному из счетчиков. В моем последнем фрагменте кода вы увидите, что я делаю ':: Number :: One'. Вы не можете делать «перечисляемый номер :: один». –

+0

@ void.pointer Работает в g ​​++. Какой компилятор вы используете? –

+0

Вы также пробовали VS 2015? –

1

Поскольку перечисление может занять диапазон значений Я хотел бы использовать множественное число здесь:

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

Это не редкость практика. Например, в Google C++ style guide они используют следующие обозначения перечислений пример:

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

Почему бы не использовать префикс для вашей Enum? Так же, как вы используете m_ для переменных-членов, вы можете использовать префикс ваших перечислений с E:

enum class ENumber 
{ 
    One, Two, Three 
}; 

Этот способ также позволяет быстро определить, что вы имеете дело с перечислением здесь, а не класс или функцию.

1

Я лично предпочитаю запускать функции-члены с помощью строчных букв и только статические (членные) функции с прописными буквами. Если есть реальная функция getter и setter, я бы также предпочел отметить их как пару, например setNumber и getNumber.

Это сам по себе был бы сделать код выглядеть следующим образом:

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

Для случая обращающегося за доступ m_number с помощью функции только по имени number я бы вернуть ссылку (или константную ссылку в константном случае):

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

В этом случае вы можете вообще избавиться от «именованной функции» и просто предоставить операторы разговора.