У меня есть файл cpp следующим образом:
#include <iostream>
#include "i.h"
using namespace std;
typedef struct abc{
int a1;
int b1;
} abc_t, *abc;
void fun(abc x){
cout<<x->a1;
}
int main(){
abc val;
fun(val);
return 0;
}
Файл i.h:
struct abc;
void fff(struct abc);
При компиляции кода возникает следующая ошибка:
t.cpp:8: error: conflicting declaration ‘typedef struct abc* abc’
t.cpp:5: error: ‘struct abc’ has a previous declaration as ‘struct abc’
t.cpp: In function ‘void fun(abc)’:
t.cpp:11: error: base operand of ‘->’ has non-pointer type ‘abc’
Если я сохраню файл cpp как файл c и скомпилирую с помощью компилятора c, все будет работать нормально. В чем проблема с компилятором С++?
Почему вы объявляете struct в файле cpp, а не в заголовочном файле?
Это не С, это С++. А в C++ у вас не может быть typedef struct abc {} *abc;





Этот
struct abc;
в C++ объявляет тип struct abc, а также тип abc, который затем снова конфликтует с typedef, снова создающим ...*abc.
В C он просто объявляет struct abc, поэтому typedef, использующий ...*abc, не создает повторяющееся объявление.
я не понял
typedef struct StructNAME {...} typedefNAME, otherTypedefNAME;, вы не можете иметь одно и то же имя для структуры и определения типа одновременно.
@KarthikKM • Один и тот же идентификатор не может означать две разные вещи.
Вы объявили abc и как структуру, и как указатель на структуру, используя typedef. Это то же самое, что:
struct abc {...};
typedef abc abc_t; // ok, abc_t is now an alias for abc
typedef abc *abc; // error
Пропустите typedef, abc_t и *abc и используйте класс (со всеми открытыми членами по умолчанию) abc как есть.
я.ч
struct abc {
int a1 = 0;
int b1 = 0;
};
void fun(const abc& x);
i.cpp
#include <iostream>
#include "i.h"
void fun(const abc& x) {
std::cout << x.a1 << "\n";
}
main.cpp
#include <iostream>
#include "i.h"
int main(){
abc val;
fun(val);
return 0;
}
В С, это:
struct abc
{
int a1;
int b1;
};
создает тип struct abc (грубо говоря), но не тип abc.
Вот почему вы используете трюк с typedef, чтобы создать тип, который мы можем использовать без необходимости везде писать struct:
typedef struct abc{
int a1;
int b1;
} abc_t;
Теперь у вас также есть тип abc_t, который совпадает с struct abc. Типа abc до сих пор нет.
Поэтому, когда вы добавляете в объявление указатель с именем abc, это допустимо, так как имя еще не занято.
В С++ исходное объявление создает тип с именем abc. Нет необходимости в трюке с typedef, и ваше объявление указателя с именем abc недействительно, поскольку занято имя abc.
Вы можете устранить неоднозначность своих имен (и распутать код) следующим образом:
struct abc
{
int a1;
int b1;
};
typedef struct abc abc_t;
abc_t* ptr_to_abc;
Или, если вы пишете на C++ и вам не нужна совместимость с C, просто так:
struct abc
{
int a1;
int b1;
};
abc* ptr_to_abc;
@TedLyngmo Потому что ОП спросил, почему это работает на C, но не на C++. Вы не можете ответить на этот вопрос, не сравнив их.
Ааа... Я не замечал до сих пор. Просто увидел тег C++ и, вероятно, отфильтровал часть C. Хороший улов.
@Ted Не могу тебя винить ?
@alk я отредактировал вопрос