Почему заголовочные файлы не могут включать друг друга? - PullRequest
0 голосов
/ 03 октября 2018

Почему я не могу сделать что-то подобное в C ++?

Ах:

#ifndef A_H
#define A_H
#include "B.h"

struct A {
    int a;
};

void doStuff1 (B b);  // Error here

#endif

Bh:

#ifndef B_H
#define B_H
#include "A.h"

struct B {
    int b;
};

void doStuff2 (A a);  // Error here

#endif

Я получаю ошибку, 'A' was not declared in this scope и то же самое с 'B'.Я знаю о предварительном объявлении, но я хотел посмотреть, возможно ли создать подобную настройку как передачу по значению вместо ссылки / указателя.Почему компилятор ведет себя так, если оба A и B фактически объявлены к тому времени, когда компилятор достигает этого кода?

Ответы [ 2 ]

0 голосов
/ 03 октября 2018

Основной урок: Включения обрабатываются до разбора любого C ++.Они обрабатываются прекомпилятором.

Допустим, что A.h включается до B.h.Вы получаете что-то вроде этого:

#ifndef A_H
#define A_H

// ----- B.h include -----    

#ifndef B_H
#define B_H
#include "A.h" // A_H is defined, so this does nothing

struct B {
    int b;
};

void doStuff2 (A a);  // Error here

#endif

// ----- B.h include -----

struct A {
    int a;
};

void doStuff1 (B b);  // Error here

#endif

На этом этапе компилятор C ++ может вступить во владение и начать анализировать вещи.Он попытается выяснить, что это за параметр doStuff2, но A еще не определен.Та же логика верна, если идти другим путем.В обоих случаях у вас есть зависимости от типов, которые еще не были определены.

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

// Example program
#include <iostream>
#include <string>

// data_types.h
struct A
{
    int x;
};

struct B
{
    int y;
};

using namespace std;
// methods_A.h
void foo(A a)
{
    a.x = 3;
    cout << "a: " << a.x << endl;
}

// methods_B.h
void bar(B b)
{
    b.y = 4;
    cout << "b: " << b.y << endl;
}

int main()
{
   A first;
   B second;
   first.x = 0;
   second.y = 100;
   foo(first);
   bar(second);
   cout << "A: " << first.x << ", B: " << second.y << endl;
}

Пример вывода

a: 3
b: 4
A: 0, B: 100
0 голосов
/ 03 октября 2018

У вас есть циркулярное включение.Вам нужно либо разделить их на разные заголовочные файлы, например, чтобы A.h и B.h объявляли только структуру / классы, а другой заголовочный файл объявлял функции.

Проблема также может быть решенаиспользуя предварительные объявления и передавая по ссылке вместо:

struct A;
struct B;

void doStuff1(A& a);
void doStuff2(B& b);
...