pliki nagłówkowe c++ zawierające się wzajemnie

Mam dwie klasy, obie zdefiniowane w osobnych plikach nagłówkowych. Każdy plik ma pole, które jest typem innej klasy. Teraz włączyłem w nagłówku KAŻDEGO pliku nagłówek innego pliku, ale kompilator generuje błędy. Co przegapiłem?

Author: Mike Nakis, 2011-12-16

4 answers

Nie możesz mieć, aby każda klasa miała "pole, które jest typem innej klasy"; byłaby to rekurencyjna definicja i nie tylko kompilator nie byłby w stanie z tego wyciągnąć żadnego sensu, nawet nie ma to logicznego sensu.

Każda klasa mająca pole, które jest typem drugiej klasy, jest rodzajem niemożliwości, którą widzisz tylko w rysunkach M. C. Eschera lub ich animacjach, takich jak Ta:

 

                                            na podstawie litografii Eschera "Print Gallery", 1956

Źródło: escherdroste.math.leidenuniv.nl

Na podstawie litografii Eschera "Print Gallery", 1956, patrz Wikipedia

 

Jedno z dwóch pól będzie musiało być wskaźnikiem , aby złamać rekurencyjne zabezpieczenie i uniknąć logicznej niemożności.

Co prowadzi nas do następnego problemu: jeśli Klasa B ma zawierać instancję klasy A, to oczywiście, A musi być zadeklarowana przed klasą B, tak że A jest znany już kompilatorowi podczas kompilacji B. Ale jeśli Klasa A jest zadeklarowana przed klasą B, jak możemy zadeklarować wskaźnik do B W A? Klasa B nie jest jeszcze znana w momencie kompilacji A! Odpowiedzią na to jest specjalna konstrukcja znana jako forward declaration, która istnieje właśnie po to, aby uwzględnić takie sytuacje. Deklaracja forward klasy B wygląda tak:

class B;

Wszystko, co mówi kompilatorowi, to to, że będzie Klasa o nazwie B. Nie powiedz kompilatorowi cokolwiek o zawartości klasy B, więc niewiele możemy z nią zrobić, ale możemy zrobić jedną rzecz: declare pointers to B.

Więc pełne rozwiązanie problemu wygląda tak:

Plik "A. h":

/* This is called a "forward declaration".  We use it to tell the compiler that the 
   identifier "B" will from now on stand for a class, and this class will be defined 
   later.  We will not be able to make any use of "B" before it has been defined, but 
   we will at least be able to declare pointers to it. */
class B;

class A
{
    /* We cannot have a field of type "B" here, because it has not been defined yet. 
       However, with the forward declaration we have told the compiler that "B" is a 
       class, so we can at least have a field which is a pointer to "B". */
    B* pb; 
}

Plik "B. h":

#include "A.h"

class B
{
   /* the compiler now knows the size of "A", so we can have a field of type "A". */
   A a;
}
 40
Author: Mike Nakis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-14 13:11:45

Nie powinieneś umieszczać plików nagłówkowych wewnątrz innych, tylko umieszczać pliki nagłówkowe w swoich plikach źródłowych.

W nagłówkach można użyć deklaracji forward:

// In Class1.h
class Class2;

// In class2.h
class Class1;

Można również zabezpieczyć przed dwukrotnym dołączeniem pliku za pomocą preprocesora:

// Class1.h
#ifndef __CLASS_1_H
#define __CLASS_1_H

// content

#endif
 17
Author: Matt Lacey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-15 21:28:33

Wiem, że to stary temat, ale może nadal jesteś zainteresowany rozwiązaniem!

Właściwie w C++ można używać dwóch klas rekurencyjnie bez używania wskaźników i oto jak to zrobić.

Plik: a. h

#include <b.h>

class A {
    B<> b;
}

Plik: b. h

class A;

template<typename T = A>
class B {
    T a;
}

Plik: main.cpp

#include "a.h"    
A a;
I to wszystko!

Oczywiście to tylko dla ciekawości :)

 12
Author: Boynux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-10 01:11:47

Prawdopodobnie chcesz użyć deklaracji forward, chyba że chcesz umieścić instancje każdej klasy w sobie. W takim przypadku nie powinieneś niczego używać.

 2
Author: Michael Krelin - hacker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-15 21:29:25