2015-06-29 5 views
-4

Я изучаю C++, и я застрял на том, почему это происходит. Этот код будет компилироваться и работать отлично, однако, если я раскомментирую //cout << foo << endl;, он не будет компилироваться.Зачем вам нужно включать, когда вы объявили об использовании?

#include <iostream> 

using namespace std; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 

    string foo = "temporary"; 

    //cout << foo << endl; 

    // Pause then exit 
    system("pause"); 
    return 0; 
} 

Я решил это, добавив: #include <string>. Может кто-нибудь сказать мне, почему это из-за меня (из C#), это не имеет смысла, почему вам разрешено создавать строковый объект, но не печатать его?

Спасибо!

+0

Idk, если вы можете полагаться на 'std :: string', включенный в' '.Кроме того, не загрязняйте глобальное пространство имен таким образом. используйте 'std ::'. – CoffeeandCode

+1

Ваша программа * уже * плохо сформирована, потому что вы не включаете заголовок ''. Вы не всегда получаете диагностику, когда совершаете ошибку на C++, но можете только утверждать, что ваша программа «работает», если вы не ошибетесь. Правила C++ не полностью исполняются компилятором. –

+0

Возможно, потому что вы используете компилятор VC++: https://ideone.com/AAmPhN – CoffeeandCode

ответ

2

Когда вы #include <iostream>, это зависит от заголовка, чтобы включить любые другие заголовки и объявления и определения, которые ему нужны - стандарт C++ не запрещает его, включая больше, чем это необходимо для обеспечения требуемой функциональности. Очевидно, что с компилятором/версиями #include <iostream> также включая достаточное количество определений, связанные с string знать, что есть template < ... > std::basic_string::basic_string(const char*); конструктора (std::string является typedef к конкретной конкретизацией basic_string для char) таким образом, что ваш код известен действительным:

string foo = "temporary"; 

Тем не менее, когда вы пошли в поток foo, он явно не видел определение соответствия ала template < ... > std::ostream& operator<<(std::ostream&, const basic_string< ... >&), который определяет, как потоковое должно быть выполнено: именно поэтому компилятор не жаловался. Определение для operator<<, вероятно, находится в вашем заголовке <string>, поэтому оно действительно необходимо перед потоковой передачей string.

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

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

+0

Я думаю, вы имеете в виду: http://www.cplusplus.com/reference/string/string/operator%3C%3C/ Спасибо за конструктивный ответ! Убирали много. – Caresi

+2

@Caresi: yes - или [здесь] (http://en.cppreference.com/w/cpp/string/basic_string/operator_ltltgtgt) - я бы рекомендовал cppreference.com через cplusplus.com - они, как правило, значительно больше точно описывая требования различных версий Стандарта. –

+0

Спасибо! cplusplus.com - это тот, который Google предлагает больше всего спасибо за подсказку! C++ так интересно учиться, и так расстраивает: D – Caresi

2

Стандартные документы библиотеки по § 21.3 [string.classes], которые используют классы строк, их члены, перегрузки операторов и т. Д., Требуют включения <string>. Любая уверенность в том, что другой заголовок делает это, либо из ваших собственных устройств, либо с каким-либо другим заголовком, чтобы включить упомянутый-то, является нестандартным, если только он не документирует его (включает <string>). Оператор вставки, который вы используете, описан в § 21.4.8.9 [string.io], но в конечном итоге применяются те же правила: включают <string>.

Вы можете предположить, что может разрешить компиляцию для успешной работы без включения <string>, избегая использования этой перегрузки вставки. Возможно, перегрузка оператора для std::basic_string включена в комплект , а не, выполненный просто с учетом <iostream>.

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

Смежные вопросы