Предописание класса, кажется, не работает в C++

От веб-сайтов, с помощью Firefox, я использую расширение CopyPlainText.

13
задан Keith Pinson 8 August 2012 в 18:22
поделиться

6 ответов

Чтобы определить класс или структуру, компилятор должен знать, насколько велика каждая переменная-член этого класса. Форвардное объявление этого не делает. Я когда-либо видел, как он используется для указателей и (реже) ссылок.

Кроме того, то, что вы пытаетесь сделать здесь, невозможно. У вас не может быть класса A, который содержит объект другого класса B, который содержит объект класса A. Вы можете , однако, чтобы класс A содержал объект указатель на класс B, который содержит объект класса A.

B.cpp

#include "B.h"

void B::SomeFunction()
{
}

Bh

#ifndef __B_h__  // idempotence - keep header from being included multiple times
#define __B_h__
#include "A.h"

class B
{
public:
    A a;
    void SomeFunction();
};

#endif // __B_h__

Ah

#ifndef __A_h__  // idempotence - keep header from being included multiple times
#define __A_h__
#include "B.h"

class B; // forward declaration

struct A
{
    B *b;  // use a pointer here, not an object
};

#endif // __A_h__

Две точки. Во-первых, обязательно используйте какую-либо форму идемпотентности, чтобы заголовки не включались несколько раз в единицу компиляции. Во-вторых, поймите, что в C ++ Единственное различие между классами и структурами - это уровень видимости по умолчанию: классы используют частную видимость по умолчанию, а структуры используют публичную видимость по умолчанию. Следующие определения функционально эквивалентны в C ++.

class MyClass
{
public: // classes use private visibility by default
    int i;
    MyClass() : i(13) { }
};

struct MyStruct
{
    int i;
    MyStruct() : i(13) { }
};
18
ответ дан 1 December 2019 в 21:12
поделиться

Здесь меня бросают в глаза две проблемы:

1: Вы написали Struct A вместо struct A ; обратите внимание на строчную букву «s». Ваш компилятор может рассмотреть эквивалент, но я не думаю, что это стандартный C ++.

Вы определили круговую ссылку между A и B . Каждый объект A должен содержать объект B , но каждый объект B должен содержать объект A ! Это противоречие, и оно никогда не будет работать так, как вы хотите. Обычный способ C ++ решить эту проблему - использовать указатели или ссылки для A :: b или B :: a (или обоих).

2
ответ дан 1 December 2019 в 21:12
поделиться
public:
    A a;

Вы пытаетесь создать объект A только с предварительным объявлением. Компилятор в этот момент (только с прямым объявлением) не может определить размер объекта A и, следовательно, он не может выделить память, необходимую для A. Таким образом, вы не можете создавать объекты только с прямым объявлением.

Вместо этого замените на:

A* a;

Указатель или ссылка на A без определения класса будет работать нормально.

3
ответ дан 1 December 2019 в 21:12
поделиться

Прямые объявления, такие как

struct A;

или

class A;

Представьте A как неполный тип , и он останется неполным до тех пор, пока не будет достигнут конец определения типа. Есть вещи, которые можно сделать с неполными типами, и то, что нельзя. Вы можете

  1. Объявить переменные (или члены) типа «указатель на A» и «ссылка на A»
  2. Объявить функции, которые принимают аргументы типа A или возвращают тип A

Вы не можете

  1. Объявить переменные (ни члены) типа A
  2. Указатели разыменования на A или доступ к любым членам ссылок на A
  3. Определите подклассы A.

В вашем коде вы пытаетесь объявить член структуры неполного типа. Это незаконно. Разрешены только указатели и ссылки.

4
ответ дан 1 December 2019 в 21:12
поделиться

Если вы создадите экземпляр A, это создаст экземпляр B (член var), который создаст экземпляр A (член var), который создаст экземпляр B, который создаст экземпляр A и так далее ... Компилятор не должен допускать этого, поскольку для этого требуется бесконечная память.

Чтобы решить эту проблему, либо A, либо B должны использовать ссылку / указатель на другой класс.

0
ответ дан 1 December 2019 в 21:12
поделиться

Вы также включаете Ah из Bh и Bh из Ah Вы должны хотя бы использовать макросы препроцессора:

#ifndef __A_H__
#define __A_H__

// A.h contents

#endif

, чтобы файл не был включен более одного раза.

0
ответ дан 1 December 2019 в 21:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: