Когда мне не нужно определение типа?

Это решение не является полностью общим, но работает для определенного типа данных:

template <class T>
class Vector {

public:

    virtual void DoSomething () {
        printf("general Vector template");
    }

};

template<>
class Vector <Vector<int>> {
public:

 void DoSomething () = delete;


};

int main(int argc, const char * argv[]) {

    Vector<int> iv;
    iv.DoSomething();  // OK;

    Vector<Vector<int>> viv;
    viv.DoSomething(); // ERROR: attempt to use a deleted function;

    return 0;
}
5
задан xtofl 5 February 2009 в 15:34
поделиться

5 ответов

Во-первых, оба объявления законны и в C и в C++. Однако в C, у них есть немного отличающаяся семантика. (В частности, способ, которым Вы обращаетесь к структуре позже, варьируется).

Ключевое понятие для понимания - то, что в C, структуры существуют в отдельном пространстве имен. Все встроенные типы, а также определения типов существуют в пространстве имен "по умолчанию". Таким образом, когда я ввожу int, компилятор только проверяет это пространство имен "по умолчанию". Если я ввожу "tagMyStruct" как в Вашем примере, компилятор также только проверяет это пространство имен. Но завися, какой тип объявления Вы используете, структура не может существовать в том пространстве имен.

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

struct mystruct {};

Я не могу просто обратиться к нему как mystruct. Вместо этого я должен указать, что хочу mystruct, который существует в пространстве имен структуры:

void foo(struct mystruct bar); // Declare a function which takes a mystruct as its parameter

Который становится немного подробным и неловким в конечном счете. Вместо этого Вы можете определение типа это в пространство имен по умолчанию:

typedef struct mystruct mystruct; // From now on, 'mystruct' in the normal namespace is an alias for 'mystruct' in the struct namespace

и теперь, моя функция может быть объявлена простым способом:

void foo(mystruct bar);

Таким образом, Ваш первый пример просто объединяет эти два шага вместе: Объявите структуру и поместите псевдоним в регулярное пространство имен. И конечно, так как мы - typedeffing это так или иначе, нам не нужно "исходное" имя, таким образом, мы можем сделать структуру анонимной. Таким образом, после Вашего объявления

typedef struct { int i; double d; } tagMyStruct;

у нас есть структура без имени, которое было typedef'ed к 'tagMyStruct' в пространстве имен по умолчанию.

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

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

Редактирование Только, чтобы быть ясным, нет, C не имеет пространств имен. Не в обычном смысле. C просто помещает идентификаторы в одно из двух предопределенных пространств имен. Названия структур (и перечисления, как я вспоминаю) помещаются в одно и все другие идентификаторы в другом. Технически, это пространства имен, потому что они - отдельные "контейнеры", в которых имена помещаются для предотвращения конфликтов, но они, конечно, не, пространства имен в C++/C# распознаются.

10
ответ дан 18 December 2019 в 07:32
поделиться

В C, если необходимо было записать

struct MyStruct { int i; double d; };

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

struct MyStruct instanceOfMyStruct;
struct MyStruct *ptrToMyStruct;

С версией определения типа:

typedef struct { int i; double d; } tagMyStruct;

только необходимо записать:

tagMyStruct instanceOfMyStruct;
tagMyStruct *ptrToMyStruct;

Другое большое преимущество с typedef'd версией состоит в том, что можно отослать к структуре тот же путь и в C и в C++, тогда как во второй версии они отнесены в по-другому в C, чем в C++.

10
ответ дан 18 December 2019 в 07:32
поделиться

Это - просто стенография.

Во втором экземпляре для объявления структуры Вы сделали бы так с:

struct MyStruct a;

В первом варианте Вы сделали бы так с:

tagMyStruct a;
1
ответ дан 18 December 2019 в 07:32
поделиться

Второй вариант также существует в C.

Вы используете первый вариант каждый раз, когда Вы хотите назвать свой тип, например:

tagEnum myFunc(tagMyStruct * myArg);
0
ответ дан 18 December 2019 в 07:32
поделиться

Первый может быть неудобным в C++, поскольку Вы не можете передать, объявляют это в заголовочном файле.

0
ответ дан 18 December 2019 в 07:32
поделиться