Учитывая класс и его класс друга, внутренние классы последнего автоматически дружат с первым классом? - PullRequest
1 голос
/ 27 марта 2012

Я пытаюсь использовать проект с открытым исходным кодом. И последняя официальная (из файла * .tar.gz), и новейшая (из SVN-репозитория) версии имеют такие вещи:

class Type1 {
    friend class Ridiculous;
    friend class Number;
    friend class Of_Friends;

    int  ImportantPrivateSemiSharedData;
};

 // In another header...

class Ridiculous {
    class Inner {
        void  MyFunc( Type1 &t )
        { /*do something with t.ImportantPrivateSemiSharedData*/ }
    };
};

AFAIK, маркировка class A как friend из class B означает , а не дает любой тип, связанный с A friend правами судна с B. Ни классы, производные от A, ни классы friend, имеющие A, не получают friend с B. Я думаю, что это ограничение относится и к внутренним классам.

Я использую компьютер с 2002 года, вернувший несколько версий операционной системы назад, в то время как программа (и, вероятно, ее команда разработчиков) в основном работает на более новых компьютерах. Мой системный компилятор просто старый и сломанный, или компиляторы new-hotness допускают что-то, чего они не должны? Это изменение в C ++ 11?

Я просто хочу использовать эту программу, но продолжаю зацикливаться на таких вещах. Я уже подозрительно, потому что код полон методов, таких как «личные данные со смешным количеством друзей» и «внутренние классы везде», которые, я думаю, являются запахами кода. Команда использует эти методы вместе, но я думаю, что они в корне несовместимы, так как friend корабль не переносит, и вы не можете заранее объявить внутренние классы.

(Если это необходимо, я использую 32-битную Mac OS X Tiger 10.4.11 / PowerPC (eMac с G4). Программа LLVM и CLang (и LLVM Test Suite), которые пробуют с обоих v3 .0 и r153311 от Subversion. Компилятор - это GCC 4.0.1, поставляемый Apple, с XCode 2.5.)

Добавление

Видя первые ответы, теперь я подозреваю, что пометка класса как друга имеет две интерпретации. Учитывая, что class A содержит friend class X, это объявление может предоставить доступ к:

  1. функция-член (static или специальная или ни одна) из X.
  2. любая функция, включая специальные, чье полное имя имеет полное имя X в качестве префикса.

Я думаю, что мой компилятор использует первое определение, а компилятор авторов использует второе. Было ли официальное слово, какое толкование является правильным? Если да, когда появилась спецификация (C ++ 98/03, отчет о дефектах, C ++ 11)? Я всегда думал, что дружба означает первую версию (включая материал C ++, который я прочитал); второй никогда не приходил мне в голову до сих пор.

1 Ответ

1 голос
/ 27 марта 2012

Я думаю, что здесь есть две проблемы.Во-первых, как вы говорите, код плохо пахнет, а во-вторых, он не компилируется в вашей системе.Что касается запаха, да, чрезмерное использование ключевого слова friend часто указывает на плохой ОО дизайн.Как правило, лучше дать объекту то, что ему нужно для выполнения своей работы, чем извлекать из него что-то, что, по сути, friend позволяет вам делать.

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

Что касается проблемы компиляции, я попытался воспроизвести ее в своей системе (Ubuntu 10.04, gcc 4.4.3, два года назадна данный момент), и создал этот пример программы:

class A
{
    friend class B;

    int x;
};

class B
{
    class Inner
    {
    public:
        void foo(A& a)
        {
            a.x++;
        }
    };

public:
    void bbb()
    {
        Inner i;
        A a;

        i.foo(a);
    }
};

int main()
{
    B b;

    b.bbb();
}

Это скомпилировано без ошибок или предупреждений.Изначально у меня ничего не было помечено как public, но мне нужно было добавить bbb(), чтобы создать экземпляр класса Inner, и мне пришлось добавить открытый метод Inner, чтобы я мог вызывать его, чтобы что-то делать с A.

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

...