Подтвердить что ты не робот

Какова цель наложения класса на С++?

Я часто видел код, похожий на следующий код кода С++, на который я смотрю:

typedef class SomeClass SomeClass;

Я в тупике по поводу того, чего это реально добивается. Похоже, это ничего не изменит. Что такое typedef, как это сделать? И если это делает что-то полезное, стоит ли прилагать дополнительные усилия?

4b9b3361

Ответ 1

См. предыдущий ответ на соответствующий вопрос. Это длинная цитата из статьи Дэн Сакса, которая объясняет эту проблему так же ясно, как и все, что я встречал:

Разница между 'struct' и 'typedef struct' в С++?

Техника может предотвратить фактические проблемы (хотя, по общему признанию, редкие проблемы).

Это дешевая битва - это нулевая стоимость во время выполнения или в кодовом пространстве (единственная стоимость - это несколько байтов в исходном файле), но защита, которую вы получаете, настолько мала, что это необычно, чтобы кто-то использовал ее последовательно, У меня есть "новый класс", который включает в себя typedef, но если я на самом деле кодирую класс с нуля без использования фрагмента, я почти никогда не беспокоюсь (или не помню?), Чтобы добавить typedef.

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

Меня попросили привести пример того, как не иметь имя класса typedef'ed может привести к неожиданному поведению - вот пример, снятый более или менее из статьи Сакса:

#include <iostream>
#include <string>

using namespace std;

#if 0   // change to #if 1 to get different behavior
        // imagine that this is buried in some header
        // and even worse - it gets added to a header 
        //     during maintenance...
string foo()
{
    return "function foo... \n";
}
#endif

class foo
{
public:
    operator string() {
        return "class foo...\n";
    }
};

int main()
{
    string s = foo();

    printf( "%s\n", s.c_str());
    return 0;
}

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

Однако, если вы включите "typedef class foo foo;", вы получите ошибку времени компиляции вместо молчаливой разницы в поведении.

Ответ 2

Это предотвращает компиляцию такого кода:

class SomeClass { ... };
int SomeClass;

Это совершенно законный С++, хотя это ужасно. Если вы сделаете это, то любые ссылки на голый SomeClass относятся к переменной. Чтобы обратиться к классу, вам нужно явно указать class SomeClass при каждом использовании. Если вы создаете typedef:

class SomeClass { ... };
typedef class SomeClass SomeClass;
int SomeClass;

Затем компилятор помещает определение int SomeClass в качестве ошибки, так как это должно быть правильно.

Ответ 3

Адам поставил правильную причину для этого, но в отношении вашего вопроса "Стоит ли проблемы" я бы дал громкую "Нет!". Возможный код проблемы:

class SomeClass { ... };
int SomeClass;

будет пойман, когда немного позже кто-то скажет:

SomeClass sc;

По общему признанию, компилятор укажет на "неправильную" строку, но такая ситуация случается так редко (я не думаю, что когда-либо видел ее в реальном коде), что она не может оправдать лес почти лишнего Определения типов.

Ответ 4

Похоже, что комментарий пытается сказать, что typedef делает символ SomeClass глобальным таким образом, чтобы никто не мог объявить локальный объект с тем же именем, который скрывает оригинальный SomeClass.

Я пробовал это с помощью VC6 (не настоящий компилятор С++, который я знаю, но лучше всего у меня есть ATM), и это, похоже, мало что делает. SomeClass все еще скрывается локальным объявлением с тем же именем. Возможно, он изменяет содержимое сообщения об ошибке для некоторого компилятора, чтобы сделать его более полезным.

Ответ 5

Мне кажется, что ваш коллега, возможно, не закончил полностью C.

В C, если вы объявите struct foo {int a;};, у вас нет ничего, что вы можете назвать просто foo, а скорее struct foo. Поэтому он довольно распространен для typedef struct foo как foo.

Это было изменено на С++, по причинам, которые должны быть достаточно очевидными.

Ответ 6

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

Ответ 7

Я понимаю концепцию различные пространства имен, которые содержат теги и идентификаторы живут, но это действительно даже стоит того набрав его?

Нет.