Перегрузочный оператор << для частного перечисления - PullRequest
1 голос
/ 19 октября 2011

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

private:
    enum supportedMessageTypes(CRITICAL = 0, WARNING, INFORMATION);
    string messages[3];

//meanwhile, inside the constructor,
messages[3] = {"Critical error message", 
               "Warning message", 
               "Information message"};

Поскольку я буду часто использовать значения enum вокруг своего кода, я бы хотел иметь возможность перегрузить operator<<, чтобы выполнить поиск значения enum, сопоставив его с соответствующей строкой в ​​массиве и вернуть это следующим образом:

cout << CRITICAL << ": " << messageText << std::endl;

Проблема, с которой я столкнулся, заключается в том, что supportedMessageTypes является закрытой, а перегрузка operator<< должна выполняться как функция, не являющаяся членом. Я знаю, что могу определить функцию friend, которая перегружает operator<< для моего класса, но мне просто не удобно нарушать инкапсуляцию таким образом, и мне было интересно, если бы кто-нибудь знал о способе перегрузки operator<< без использования friend функции или сделать supportedMessageTypes публичным?

Ответы [ 3 ]

2 голосов
/ 19 октября 2011

Это невозможно.Вы хотите принять аргумент типа supportedMessageTypes, поэтому он должен быть видимым.Обойти это невозможно.

Кроме того, функция friend не будет плохой;это один из намеченных сценариев дружбы.

0 голосов
/ 19 октября 2011

Я не могу согласиться с некоторыми предпосылками в вашем вопросе. В частности, когда вы говорите, что объявление operator<< как функции friend нарушает инкапсуляцию. Он нарушает инкапсуляцию точно так же, как любая функция-член вашего типа нарушает инкапсуляцию. operator<< является частью вашего типа и имеет доступ к private частям, но это не нарушение инкапсуляции. Обратите внимание, что в C ++ не только функции-члены принадлежат интерфейсу типа. Google для принцип интерфейса .

class test {
   enum E { ok, nok };
   friend std::ostream& operator<<( std::ostream&, E );
};
std::ostream& operator<<( std::ostream& out, E e ) {
   if ( e == ok ) out << "ok";
   else out << "nok";
   return out;
}

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

class test {
    enum E { ok, nok }
    friend std::ostream& operator<<( std::ostream& out, E e ) {
       if ( e == ok ) out << "ok";
       else out << "nok";
       return out;
    }
};

Как этот код менее инкапсулирован , чем ваш исходный код?

0 голосов
/ 19 октября 2011

http://ideone.com/gMTZ6

Несмотря на все мои усилия, я не смог найти способ сделать это без ключевого слова friend.С другой стороны, это не нарушает инкапсуляцию, поскольку никто за пределами вашего класса не может использовать функцию, поскольку они не могут получить доступ к типу, используемому в поиске типов.Ergo, вы все еще полностью заключены в капсулу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...