Есть ли способ, чтобы typedef это? - PullRequest
1 голос
/ 25 августа 2009

Упрощенная версия кода:

foo.h:

class Foo {
    private:
        class Bar {
            // ...
        };
        typedef std::map<int, Bar> mapType;
        mapType _map;
    public:
        void method(mapType::iterator it);
};

foo.cpp:

void Foo::method(mapType::iterator it) {
    // ...
    notMethod(it);
}

void notMethod(mapType::iterator it) {
    // ...
}

Неудивительно, что я получаю ошибку 'mapType' is not a class or namespace name в VS2008 при определении notMethod. Есть ли какой-нибудь (изящный) способ, которым я мог бы избежать необходимости вводить std::map<int, Bar> в каждом определении notMethod, не превращая notMethod в метод?

Ответы [ 4 ]

20 голосов
/ 25 августа 2009

Используйте

void notMethod(Foo::mapType::iterator it) {
    // ...
}

и поместите typedef в публичный раздел объявления класса Foo.

Edit:

Если вы хотите избежать этого, вы можете

  1. сделать notMethod другом (в соответствии с предложением DanDan),
  2. используйте шаблонное решение sbi или
  3. делает notMethod закрытой статической функцией-членом Foo (которая генерирует точно такой же код, как если бы это была свободная функция, не являющаяся членом).

Какое решение является наиболее подходящим, зависит от того, что делает notMethod.

Если notMethod использует Bar и Bar действительно имеет смысл только в контексте внутренней реализации Foo, я бы сделал notMethod частной статической функцией-членом, поскольку она является частью Foo внутренние органы.

Если notMethod был оператором, который должен принять не-1034 * в качестве первого аргумента (это означает, что он не может быть членом Foo), и если я хотел оставить Bar закрытым Я бы сделал оператора другом.

Если notMethod реализует универсальную операцию на итераторах, я бы сделал ее функцией шаблона.

Если Bar - это класс, который может представлять интерес для клиентов Foo, я бы сделал Bar и typedef общедоступным и использовал бы решение, которое я предложил изначально.

4 голосов
/ 25 августа 2009

Опираясь на ответ Мартина Б:

Причина, по которой notMethod не знает тип mapType , заключается в том, что он находится внутри класса Foo , классы можно представить как пространства имен в этом случае, если хотите.

В любом случае, вы должны изменить код на:

void notMethod(Foo::mapType::iterator it) {}

Если вы согласны с Мартином Б, вы должны переместить typedef в раздел public класса. Если вы согласны с DanDan, вы должны Друг функция.

Myself? Я бы поместил typedef вне класса и поместил и класс, и typedef в пространство имен .

4 голосов
/ 25 августа 2009

Друзья .

Добавить

friend void notMethod(mapType::iterator it);

для вашего класса Foo, и вы можете хранить свои внутренние классы и функции в секрете.

3 голосов
/ 25 августа 2009

Мартин Б предоставил вам ответ . Вот альтернатива:

Ваш notMethod() выглядит для меня как деталь реализации, которая, вероятно, определена в безымянном пространстве имен файла cpp. В этом случае я обычно делаю шаблон notMethod():

template< typename It >
void notMethod(It it) {
    // ...
}

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

...