Конфликтующее объявление в c ++ - PullRequest
0 голосов
/ 25 января 2019

У меня есть файл 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, то все будет работать нормально. В чем проблема с компилятором c ++?

Ответы [ 3 ]

0 голосов
/ 25 января 2019

Вы объявили 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 как есть.

i.h

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;
}
0 голосов
/ 25 января 2019

В С , это:

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, это действительно, так как имя еще не занято.


В C ++ исходное объявление создает тип с именем 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;
0 голосов
/ 25 января 2019

Этот

struct abc;

в C ++ объявляет тип struct abc, а также тип abc, который затем снова конфликтует с typedef 'ing ...*abc.

В C он просто объявляет struct abc, поэтому typedef 'ing ...*abc не создает дублирующую декларацию.

...