Ошибка переопределения класса C ++ — помогите мне понять заголовки и ссылки

Я начал писать простой интерпретатор в C ++ со структурой классов, которую я опишу ниже, но я бросил и переписал эту вещь в Java, потому что заголовки доставляли мне трудные времена. Вот основная структура, которая явно не разрешена в C ++:

main.cpp содержит основную функцию и включает в себя заголовок для класса, который мы можем вызвать printer.h (чей единственный метод void реализован в printer.cpp). Теперь представьте два других класса, которые идентичны. Оба хотят позвонить Printer::write_something();так я включил printer.h в каждом. Итак, вот мой первый вопрос: почему я могу #include <iostream> миллион раз, даже один за другим, но я могу только включить мой заголовок один раз? (Ну, я думаю, что я мог бы сделать то же самое с моим, если он находится в том же файле. Но я могу ошибаться.) Я понимаю разницу между объявлением и реализацией / определением, но этот код дает мне Ошибка переопределения класса. Я не понимаю почему. И вот что поражает меня (и, вероятно, показывает, почему я ничего не понимаю): я не могу просто включить printer.h на вершине main.cpp и использовать класс из моих двух других классов. Я знаю, что могу включить printer.h в один из двух классов (заголовков) без проблем, но я не понимаю, почему это отличается от простого включения до того, как я включил класс в main.cpp (как это делает мне класс не найдена ошибка).

Когда я сыт по горло, я думал о переходе на C, так как используемый мной ООП в любом случае был довольно вынужденным, но я столкнулся бы с той же проблемой, если не записал все в один файл. Очень неприятно знать C ++, но не могу правильно его использовать из-за проблем с компиляцией.

Я был бы очень признателен, если бы вы могли прояснить это для меня. Спасибо!

2

Решение

Почему я могу включить миллион раз, даже один за другим, но мой заголовок я могу включить только один раз?

Это, вероятно, потому что ваш заголовок не имеет включить охрану.

// printer.h file
#ifndef PRINTER_H_
#define PRINTER_H_

// printer.h code goes here

#endif

Обратите внимание, что рекомендуется выбирать более длинные имена для определений include guard, чтобы минимизировать вероятность того, что два разных заголовка могут иметь один и тот же заголовок.

4

Другие решения

Большинство заголовочных файлов должны быть упакованы в include guard:

#ifndef MY_UNIQUE_INCLUDE_NAME_H
#define MY_UNIQUE_INCLUDE_NAME_H

// All content here.

#endif

Таким образом, компилятор будет видеть содержимое заголовка только один раз на единицу перевода.

3

Компиляция C / C ++ делится на блоки компиляции / трансляции для генерации объектных файлов. (.o, .obj)

смотрите здесь определение единицы перевода

Директива #include в файле C / C ++ приводит к прямому эквиваленту простой рекурсивной копирования-вставки в том же файле. Вы можете попробовать это в качестве эксперимента.

Таким образом, если один и тот же модуль перевода включает в себя один и тот же заголовок дважды, компилятор видит, что некоторые сущности определяются несколько раз, как это было бы, если бы вы записали их в один и тот же файл. Вывод ошибки будет точно таким же.

В языке нет встроенной защиты, которая мешает вам делать несколько включений, поэтому вам приходится прибегать к написанию шаблона include guard или конкретного шаблона #pragma для каждого заголовка C / C ++.

0
По вопросам рекламы [email protected]