Заголовочные файлы C++, разделение кода

Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals для гарантированного непустого объекта.

Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null.

Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

29
задан Beryllium 5 March 2015 в 19:54
поделиться

4 ответа

Заголовочные файлы должны содержать объявления класса и объявления функции.

Исходные файлы содержат класс и функциональные определения.

Это - общепринятая практика (т.е. читайте легче) иметь одно объявление на заголовочный файл и одно определение на исходный файл, хотя для маленького (читает более простого помощника) возражает, что Вы иногда группируете их со связанными более существенными объектами.

Пример: Меню

Menu.h:     Contains the Menu declaration.
Menu.cpp:   Contains the Menu definition.

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

Считают его этим путем:
, Если бы у Вас не было заголовочных файлов тогда, у Вас должны были бы быть объявления класса и/или объявления функции (без) определений в каждом исходном файле, это означает копию того же объявления в каждом файле. Таким образом при изменении класса, необходимо сделать ту же модификацию в каждом файле. При помощи заголовочного файла у Вас есть объявление в одном месте и таким образом только одном объекте изменить.

25
ответ дан Martin York 28 November 2019 в 01:36
поделиться

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

Единица перевода

Единица перевода А является текущим кодом, скомпилированным и всем кодом, включенным им, прямо или косвенно. Одна Единица перевода переводит в один.o / .obj файл.

Программа

Это - весь Ваш.o / .obj файлы, соединенные в один двоичный файл, который может быть выполнен для формирования процесса.

, Каковы основные моменты наличия различных единиц перевода?

  1. Уменьшают зависимости, так, чтобы при изменении одного метода одного класса Вы не перекомпилировали весь код своей программы, но только затронутую единицу перевода.
  2. Уменьшают возможные столкновения имени при наличии единицы перевода локальные имена, которые не видимы другой единицей перевода при соединении их.

Теперь, как можно разделить код на различные единицы перевода? Ответ существует не, "таким образом, Вы делаете это!", но необходимо рассмотреть его в зависимости от конкретного случая. Это часто ясно, так как у Вас есть различные классы, которые могут и должны быть помещены в различные единицы перевода:

foo.hpp:

/* Only declaration of class foo we define below. Note that a declaration
 * is not a definition. But a definition is always also a declaration */
class foo;

/* definition of a class foo. the same class definition can appear 
   in multiple translation units provided that each definition is the same  
   basicially, but only once per translation unit. This too is called the  
   "One Definition Rule" (ODR). */
class foo {
    /* declaration of a member function doit */
    void doit();

    /* definition of an data-member age */
    int age;
};

Объявляют некоторые бесплатные функции и объекты:

/* if you have translation unit non-local (with so-called extern linkage)  
   names, you declare them here, so other translation units can include  
   your file "foo.hpp" and use them. */
void getTheAnswer();

/* to avoid that the following is a definition of a object, you put "extern"  
   in front of it. */
extern int answerCheat;

foo.cpp:

/* include the header of it */
#include "foo.hpp"

/* definition of the member function doit */
void foo::doit() {
    /* ... */
}

/* definition of a translation unit local name. preferred way in c++. */
namespace {
    void help() {
        /* ... */
    }
}

void getTheAnswer() {
    /* let's call our helper function */
    help();
    /* ... */
}

/* define answerCheat. non-const objects are translation unit nonlocal  
   by default */
int answerCheat = 42;

bar.hpp:

/* so, this is the same as above, just with other classes/files... */
class bar {
public:
    bar(); /* constructor */
}; 

bar.cpp:

/* we need the foo.hpp file, which declares getTheAnswer() */
#include "foo.hpp"
#include "bar.hpp"

bar::bar() {
    /* make use of getTheAnswer() */
    getTheAnswer();
}

Обратите внимание на то, что имена в анонимном пространстве имен (как выше) не сталкиваются, так как они, кажется, локальная единица перевода. в действительности они не, у них просто есть уникальные имена так, чтобы они не сталкивались. если Вы действительно хотите (существует мало причины для) единица перевода локальные имена (например, из-за совместимости с c, таким образом, C код может вызвать Вашу функцию), можно сделать это как это:

static void help() { 
    /* .... */
}

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

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

21
ответ дан Johannes Schaub - litb 28 November 2019 в 01:36
поделиться

Решение, как разделить Ваш код на различные классы/функции, является одной из основных задач программирования. Существует много различных инструкций по тому, как сделать это, и я рекомендовал бы читать некоторые учебные руководства на C++ и Объектно-ориентированном проектировании для запущения Вас.

Некоторые основные инструкции будут

  • Помещенные вещи вместе, которые используются вместе
  • , Создают классы для объектов области (например, файлы, наборы и т.д.)

, Заголовочные файлы позволяют Вам объявлять класс или функцию и затем использовать ее в нескольких файлах другого источника. Например, если Вы объявляете класс в заголовочном файле

// A.h
class A
{
public:
    int fn();
};

, можно тогда использовать этот класс в нескольких исходных файлах:

// A.cpp
#include "A.h"
int A::fn() {/* implementation of fn */}

//B.cpp
#include "A.h"
void OtherFunction() {
    A a;
    a.fn();
}

, Таким образом, заголовочные файлы позволяют Вам разделить объявление от реализации. Если необходимо было поместить все (объявление и реализация) в исходном файле (например, A.cpp) тогда пытаются включать это во второй файл, например,

// B.cpp
#include  "A.cpp" //DON'T do this!

Тогда Вы могли скомпилировать B.cpp, но когда Вы попытаетесь связать свою программу, компоновщик будет жаловаться, что Вы имеете, умножают определенные объекты - это вызвано тем, что у Вас есть несколько копий реализации A.

4
ответ дан Eric 28 November 2019 в 01:36
поделиться

Предложение: 1. Имейте дизайн, готовый к Вашему приложению теперь. 2. На основе дизайна создайте необходимые объекты, которые взаимодействуют друг с другом. 3. Осуществите рефакторинг или полностью измените существующий код для удовлетворения недавно созданному дизайну.

Заголовочные файлы предоставляют интерфейс другим классам, которые могли бы использовать, это - функциональность.

0
ответ дан Elroy 28 November 2019 в 01:36
поделиться
Другие вопросы по тегам:

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