Исходные файлы с описанием класса

 
0
 
C++
ava
efpies | 18.01.2011, 16:23
Здравствуйте.
Очень ламерский вопрос, на самом деле.

У меня в проекте несколько классов. Как было бы правильно их разбивать по файлам? Каждый класс в отдельный cpp-файл? Или в h-файл? Или в h-файле - прототипы и константы, а в cpp, который подключён к h, - описание? Как правильно?
Ответы (55)
ava
KaraKum | 18.01.2011, 16:32 #
Некоторые фанатики каждый класс описывают в отдельном .h-файле (называя файл так же как и класс но только маленькими буквами и разделяя слова пробелами - получается ужасно).
Можно делить объявления классов по логическим признакам. Например классы отвечающие за графику - в одном файле; за логику - в другом. Общих нареканий в этой области нет (в отличии от, например, по оформлению кода (самая известная - GNU-style)).
Код определения функций можно писать прямо в объявлении этих функций (в .h-файле) если подразумевается что файл будет подключаться к проекту только в одном месте (что как раз это подчёркивает)
Не забывать что можно писать и "#include "definition.cpp"" - то есть вообще обойтись без header'ов  :smile

Добавлено позднее:
В остальном могут быть только какие-то частные нарекания. Например какие-то глобальные переменные (как же без них) можно определить в "globals.cpp":

namespace Globals
{
     int someGlobalVariable = 0;
     ClassName *someGlobalClassInstance = new ClassName;
}//namespace Globals

И создать вот такой "externs.h", который можно подключать в любом другом файле где нужно использовать глобальные переменные:

#ifndef EXTERNS_H
#define EXTERNS_H

namespace Globals
{
     extern int someGlobalVariable;
     extern ClassName *someGlobalClassInstance;
}//namespace Globals

#endif//#ifndef EXTERNS_H


Добавлено позднее:
Вообще, все эти проблемы решаются как сами собой разумеющиеся после должного проектирования программы (перед её написанием или в процессе). Для этого можно пользоваться средствами ООПTDD и общие принципы проектирования рисованием графовUML-диаграмм...
ava
mes | 18.01.2011, 17:08 #
Цитата(KaraKum @  18.1.2011,  15:32 findReferencedText)
Не забывать что можно писать и "#include "definition.cpp"" - то есть вообще обойтись без header'ов  

и нажить проблем smile
ava
KaraKum | 18.01.2011, 17:08 #
Цитата(mes @ 18.1.2011,  18:08)
Цитата(KaraKum @  18.1.2011,  15:32 \\"findReferencedText\\")
Не забывать что можно писать и "#include "definition.cpp"" - то есть вообще обойтись без header'ов  


и нажить проблем smile

Именно.
ava
mes | 18.01.2011, 17:09 #
Цитата(KaraKum @  18.1.2011,  15:32 findReferencedText)
Некоторые фанатики каждый класс описывают в отдельном .h-файле

далеко не только фанатики...
ava
KaraKum | 18.01.2011, 19:41 #
Цитата(mes @ 18.1.2011,  18:09)
Цитата(KaraKum @  18.1.2011,  15:32 \\"findReferencedText\\")
Некоторые фанатики каждый класс описывают в отдельном .h-файле


далеко не только фанатики фанатики...

Скорее-всего я неясно высказался.
Иногда бывает что какие-то структуры используются только внутри какой-то одной функции - такие структуры вполне логично объявлять внутри самой этой функции, однако некоторые ФАНАТИКИ выделят для этой структуры отдельный файл, назвав этот файл в её честь.  smile 
ava
borisbn | 18.01.2011, 21:06 #
2 TS:  пишу с КПК в автобусе, поэтому коротко: KaraKum дал тебе ОЧЕНЬ плохие советы. Что про несколько классов в одном h-нике, что инклюд срр-шника, что про глобальные переменные. Чуть позже подробнее отпишусь 
ava
KaraKum | 18.01.2011, 22:42 #
Опаньки  smile 
Ну вот - TS в чрезвычайном режиме спасли от моих смертельных советов  :smile

Добавлено позднее:
Кстати, инклудить .cpp-файлы я не советовал - сказал лишь что это возможно. А вот объявление нескольких классов в одном хедере и глобальные переменные - это советовал (описал как это делать).
ava
borisbn | 19.01.2011, 10:43 #
Цитата(KaraKum @  18.1.2011,  22:42 findReferencedText)
не советовал - сказал лишь что это возможно

у новичков часто строится такая цепочка "возможно-так можно делать-так делают-так делают все-так нужно делать". Возможно ещё создавать функции на 2000 строк, делать такие конструкции ( пару лет назад достался проект по наследству, так я этот кусок сохранил, чтобы показывать как не надо делать )

// Построение гистограммы
Histogramm[szMin - MIN_LEVEL + int(*pMP++)]++;

и т.п., однако сообщать новичкам, что это всё возможно IMHO не стОит.
Теперь о нескольких классах в одном хедере. Если класс настолько маленький и простенький, что для него не нужен отдельный файл, то его и создавать не нужно, скорее всего можно обойтись "свободными" функциями ( исключения составляют лишь функторы, но с приходом стандарта 0x00 и в них не будет особой необходимости ). Если же класс сложнее, чем пару функций get/set и если он создан для того, чтобы повторно его использовать ( и не в одном проекте, а в многих последующих ), то его просто необходимо вынести в отдельный файл. Так ведь даже удобнее.
А глобальные переменные ( не константы ) - вообще зло, т.к. сегодня тебе хватает производительности, а завтра - нет, и приходится распараллеливать программу, делать несколько потоков... далее, думаю, понятно.

P.S. Кажется TS уже забыл о нас, и всё это превращается во флуд. Предлагаю засим закончить smile
ava
efpies | 19.01.2011, 11:09 #
TS мониторит тему потихоньку)
Спасибо за советы.

Почему у меня возник такой вопрос: вот пишут, что
Цитата


Заголовочный файл в общем случае может содержать любые конструкции языка программирования, но на практике исполняемый код (за исключением inline-функций в C++) в заголовочные файлы не помещают.



Ну хорошо, сейчас у меня каждый класс в отдельном h-файле (каждый строк на 200, потому всё в один файл пихать - это будет кровавое месиво, тем более каждый класс считай как модуль), который имеет имя такое, как класс. Насколько это верно с учётом этой цитаты?) Да и вообще при каком-либо изменении какого-либо класса нужно сначала сделать build, а только потом run (видимо, сказывается специфика h-файлов), что сказывается на отладке не лучшим образом. Вот мне и подумалось, а не в cpp-файлы ли помещать их описание и т.д.? Ну и соответственно, что будет являться "хорошим стилем".
ava
borisbn | 19.01.2011, 11:54 #
efpies, самая общепринятая практика следующая: в h-файлах класс описывается, а в cpp-файлах - определяется. Описание класса - есть интерфейс (договор, контракт) между тем, кто его создаёт и тем, кто его будет использовать. Определение класса - это уже не договор, а испольнение договора, причём только тем, кто его создаёт. При этом, если ты изменяешь договор между разработчиком класса и его потребителем, то тебе необходимо перекомпилировать и сам класс, и те исходники, которые его используют. Если же ты меняешь только ход исполнения договора, при этом контракт остаётся нетронутым, то достаточно только перекомпилировать исходник класса. А вообще без перекомпиляции при изменении в Си/Си++ никак. Это не скриптовый язык.
Вот пример нормальной организации класса и его использования:
SomeClass.h

#if !defined( _SOME_CLASS_H_INCLUDED_ )
#define _SOME_CLASS_H_INCLUDED_

class SomeClass {
public:
  SomeClass();
  ~SomeClass();
  void foo();
private:
  int m_x;

  void bar();
};
#endif //!defined( _SOME_CLASS_H_INCLUDED_ )


SomeClass.cpp

#include "SomeClass.h"

SomeClass::SomeClass()
  : m_x( 0 )
{
}

SomeClass::~SomeClass() {
}

void SomeClass::foo() {
}

void SomeClass::bar() {
}


SomeClassUsing.h (использование SomeClass)

#if !defined( _SOME_CLASS_USING_H_INCLUDED_ )
#define _SOME_CLASS_USING_H_INCLUDED_

class SomeClass;

class SomeClassUsing {
public:
  SomeClassUsing();
  ~SomeClassUsing();
private:
  SomeClass * m_someClass;
};
#endif //!defined( _SOME_CLASS_USING_H_INCLUDED_ )


SomeClassUsing.cpp (использование SomeClass)

#include "SomeClassUsing.h"
#include "SomeClass.h"

SomeClassUsing::SomeClassUsing() {
  m_someClass = new SomeClass();
}

SomeClassUsing::~SomeClassUsing() {
  delete m_someClass;
}

ava
KaraKum | 19.01.2011, 13:13 #
Вот тут вот рисованные карандашом картинки могут быть интересны.
ava
efpies | 19.01.2011, 21:30 #
borisbn, KaraKum, спасибо за наглядные ответы! :)


Цитата(borisbn @  19.1.2011,  11:54 findReferencedText)
А вообще без перекомпиляции при изменении в Си/Си++ никак. Это не скриптовый язык.

Это понятно, просто либо компилятор сам перекомилирует, либо я это делаю насильно. Это я имел в виду.

Возник такой вопрос: к примеру, у меня есть 2 h-файла и 2 соответствующих cpp-файла (то есть, как Вы описали). Что в конечном итоге включается в использующий файл? Ну я имею в виду, что если мы включим в main.cpp SomeClassUsing.h, он же не будет знать о существовании SomeClassUsing.cpp, поскольку в заголовочном файле он никак не затрагивается. Или компилятор будет знать "по умолчанию" о существовании cpp-файла, поскольку имена одинаковые?
ava
KaraKum | 19.01.2011, 22:59 #
Я уже даже боюсь отвечать, ато теперь не из автобуса "по рации" сообщат о некомпетентности, а в квартиру постучат и конвоируют  smile 

"Превращение исходного кода в исполняемый" выполняется в два этапа: компиляция и, затем, компоновка (есть ещё препроцессор, но его относят к компиляции).
В процессе компиляции формируется никак не связанный набор функций (в том числе и main()). Процесс компиляции в местах вызовов функций лишь проверяет факт их описания (существования) и, конечно, вызываемые параметры. При компоновке на места вызовов функций располагаются уже настоящие адреса расположения этих функций (их исполняемые варианты, созданные в процессе компиляции) - если компоновщик не находит какую-либо скомпилированную функцию, то будет ругаться и откажется компилировать.
Поэтому если не указать .cpp файлов, то процесс компиляции может завершиться успешно, но компоновка нет.
ava
mes | 19.01.2011, 23:06 #
Цитата(efpies @  19.1.2011,  20:30 findReferencedText)
. Или компилятор будет знать "по умолчанию" о существовании cpp-файла, поскольку имена одинаковые? 

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


ava
KuMa1104 | 20.01.2011, 00:57 #
Всем здрасте)))
 
Цитата(borisbn @  19.1.2011,  11:54 findReferencedText)
efpies, самая общепринятая практика следующая: в h-файлах класс описывается, а в cpp-файлах - определяется. Описание класса - есть интерфейс (договор, контракт) между тем, кто его создаёт и тем, кто его будет использовать. Определение класса - это уже не договор, а испольнение договора, причём только тем, кто его создаёт. При этом, если ты изменяешь договор между разработчиком класса и его потребителем, то тебе необходимо перекомпилировать и сам класс, и те исходники, которые его используют. Если же ты меняешь только ход исполнения договора, при этом контракт остаётся нетронутым, то достаточно только перекомпилировать исходник класса. А вообще без перекомпиляции при изменении в Си/Си++ никак. Это не скриптовый язык.

Вот пример нормальной организации класса и его использования:

SomeClass.h

код C++

#if !defined( _SOME_CLASS_H_INCLUDED_ )

#define _SOME_CLASS_H_INCLUDED_ 

class SomeClass {

public:

  SomeClass();

  ~SomeClass();

  void foo();

private:

  int m_x;

  void bar();

};

#endif //!defined( _SOME_CLASS_H_INCLUDED_ )





SomeClass.cpp

#include "SomeClass.h"

SomeClass::SomeClass()

  : m_x( 0 )

{

}

SomeClass::~SomeClass() {

}

void SomeClass::foo() {

}

void SomeClass::bar() {

}



А можно в .cpp файле добавить новые функции члены класса?

void SomeClass::NewMetod() {

У меня компилятор визжит на такое, это вообще возможно?

Добавлено позднее:
private я имею в виду конечно.
ava
borisbn | 20.01.2011, 09:07 #
Цитата(KuMa1104 @  20.1.2011,  00:57 findReferencedText)
А можно в .cpp файле добавить новые функции члены класса?

Вот тебе и ответ.
Цитата(KuMa1104 @  20.1.2011,  00:57 findReferencedText)
У меня компилятор визжит на такое, это вообще возможно?

Нет. К сожалению.
ava
KuMa1104 | 20.01.2011, 23:20 #
Цитата(borisbn @  20.1.2011,  09:07 findReferencedText)
Вот тебе и ответ.

Цитата(KuMa1104 @  20.1.2011,  00:57 )

У меня компилятор визжит на такое, это вообще возможно?

Да пожалуй действительно железный довод)
ava
bsa | 20.01.2011, 23:34 #
KuMa1104, а почему нельзя и в объявление класса добавить?
ava
mes | 20.01.2011, 23:51 #
Цитата(borisbn @  19.1.2011,  10:54 findReferencedText)
  в h-файлах класс описывается, а в cpp-файлах - определяется. 

 smile,
Цитата


A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the

class-specifier.


т.е. определение (definition) класса "происходит" в хидере..
 smile 
ava
borisbn | 21.01.2011, 00:16 #
Цитата(mes @  20.1.2011,  23:51 findReferencedText)
определение (definition)

перевод definition:

определение
четкость
описание
дефиниция
толкование
резкость
точность
ясность

Т.о. вопрос только в переводе, а если прочитать полностью
Цитата(borisbn @  19.1.2011,  11:54 findReferencedText)
Описание класса - есть интерфейс (договор, контракт) между тем, кто его создаёт и тем, кто его будет использовать. Определение класса - это уже не договор, а испольнение договора

а не выдёргивать, то получается вполне стройно smile
ava
mes | 21.01.2011, 00:21 #
Цитата(borisbn @  20.1.2011,  23:16 findReferencedText)
Т.о. вопрос только в переводе, а если прочитать полностью

нет, вопрос в устоявшихся терминах :)

Добавлено позднее:
Цитата(borisbn @  20.1.2011,  23:16 findReferencedText)
, а если прочитать полностью

Цитата(KuMa1104 @  19.1.2011,  23:57 findReferencedText)
 Описание класса - есть интерфейс 

Цитата(KuMa1104 @  19.1.2011,  23:57 findReferencedText)
. Определение класса - это уже не договор, а испольнение договора, 

 smile  smile 
ava
borisbn | 21.01.2011, 07:19 #
mes, ОК, сдаюсь. Не силён в терминологии smile
Скажи, пожалуйста, как в устоявшемся виде называют интерфейс класса, а как - реализацию его функций ?
ava
mes | 21.01.2011, 11:57 #
class Class; // объявление класса

class Class {
       void f();  // объявление (прототипа) функции-члена
}; // определение класса

void Class::f() {} // определение функции-члена

ava
borisbn | 21.01.2011, 15:15 #
mes, я прекрасно понимаю, что о терминологии (тем более о переводе) можно спорить долго и, практически всегда, безрезультатно, однако...

Цитата(mes @  21.1.2011,  11:57 findReferencedText)
class Class; // объявление класса

чесслово, всегда считал это предварительным объявлением (или предобъявлением) ...

а по поводу
Цитата(mes @  21.1.2011,  11:57 findReferencedText)
}; // определение класса

вот тут
нашёл гениальную фразу
Цитата


Как сказано в Справочном руководстве по C++, "Если бы не исторические причины, объявление класса следовало называть определением класса".



так что предлагаю ничью smile
ava
mes | 21.01.2011, 18:31 #
Цитата(borisbn @  21.1.2011,  14:15 findReferencedText)
я прекрасно понимаю, что о терминологии (тем более о переводе) можно спорить долго и, практически всегда, безрезультатно, однако...

в данном случае спор не о словax "определение" и "описание"..  а о том, что определение/описание класса не затрагивает определение функций-членов..


Цитата(borisbn @  21.1.2011,  14:15 findReferencedText)
всегда считал это предварительным объявлением (или предобъявлением) ...

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

class Class; // forward declaration
class Class {}; //  declaration by definition
class Class; // backward declaration


Цитата(borisbn @  21.1.2011,  14:15 findReferencedText)
вот тут

нашёл гениальную фразу

сейчас почитаю..
ava
baldina | 21.01.2011, 18:31 #
KaraKum, используешь "нарекание" с странном, не общеупотребительном значении. звучит забавно
http://ru.wiktionary.org/wiki/%D0%BD%D0%B0...%BD%D0%B8%D0%B5

Цитата(KaraKum @  18.1.2011,  16:32 findReferencedText)
все эти проблемы решаются как сами собой разумеющиеся после должного проектирования программы

о проектировании структуры кода, его организации и спрашивает ТС

Цитата(efpies @  19.1.2011,  21:30 findReferencedText)
 Или компилятор будет знать "по умолчанию" о существовании cpp-файла

efpies, в С/С++ используется т.н. раздельная компиляция, т.е. компилятор знает лишь о том файле, который компилирует в данный момент. содержимое включаемого файла в буквальном смысле подставляется в место директивы #include и компилируется результат.
таким образом заголовочные файлы являются средством связи между файлами .сpp, при помощи них объявляются типы и переменные, определенные в другом файле.
отдельный файл в C/C++ является не только единицей компиляции, но и средством структуризации программ (другие средства - функции, структуры и классы, пространства имен). К ним в общем случае применимы те же правила, что и к любым средствам структуризации: одна задача (тема, понятие) - один файл (класс, функция). интуитивно понять, как это лучше сделать, можно посмотрев на содержимое стандартных заголовков: cmath, ctime, vector, map, iostream, string.
Если речь идет о классах, то один заголовок - один класс (плюс, возможно, классы, связанные с ним и только с ним непосредственно. например string и string_iterator).
Конечно, в любом правиле бывают исключения, все должно быть по уму и без фанатизма.
Для упрощения анализа и отладки, для сокращения времени компиляции число связей в проекте, в т.ч. связей между файлами, стараются уменьшить.
пример borisbn вполне иллюстрирует основу такого подхода.

Добавлено позднее:
mesborisbn, не спорьте. в русскоязычной терминологии на эту тему небольшой бардак.
объявление (declaration) - ввод идентификатора в текущую область видимости. при этом объявление может быть определением. а может и не быть, как, например, опережающее объявление.
ava
mes | 21.01.2011, 18:44 #
Цитата(mes @  21.1.2011,  17:31 findReferencedText)
сейчас почитаю.. 


о нет, такое читать не буду..  :bad

Цитата(borisbn @  21.1.2011,  14:15 findReferencedText)
так что предлагаю ничью  

ну ну, пожалуйста.. не буду Вас разубеждать.. продолжайте читать Марченко.. :girl_crazy

Добавлено позднее:
Цитата(baldina @  21.1.2011,  17:31 findReferencedText)
 не спорьте. в русскоязычной терминологии на эту тему небольшой бардак.


Цитата(mes @  21.1.2011,  17:31 findReferencedText)
в данном случае спор не о словax "определение" и "описание"..  а о том, что определение/описание класса не затрагивает определение функций-членов..

 smile 

Цитата(baldina @  21.1.2011,  17:31 findReferencedText)
 при этом объявление

как раз конфликта между "объявление" и "определение" нету..
есть спор какое из слов "определение" или "описание" подходит в качестве перевода для "definition" в некоторых случаях...
ava
baldina | 21.01.2011, 18:50 #
Цитата(mes @  21.1.2011,  18:44 findReferencedText)
Цитата(mes @  21.1.2011,  17:31 )

в данном случае спор не о словax "определение" и "описание"..  а о том, что определение/описание класса не затрагивает определение функций-членов..


с этим borisbn вроде бы и не спорил. а насчет перевода... definition можно перевести как описание. если рядом нет declaration.
ava
mes | 21.01.2011, 19:06 #
Цитата(baldina @  21.1.2011,  17:50 findReferencedText)
с этим borisbn вроде бы и не спорил. 


Цитата(borisbn @  20.1.2011,  23:16 findReferencedText)


Т.о. вопрос только в переводе, а если прочитать полностью

Цитата(borisbn @  19.1.2011,  11:54 )

Описание класса - есть интерфейс (договор, контракт) между тем, кто его создаёт и тем, кто его будет использовать. Определение класса - это уже не договор, а испольнение договора



а не выдёргивать, то получается вполне стройно 

:wink

Добавлено позднее:
Цитата(baldina @  21.1.2011,  17:50 findReferencedText)
definition можно перевести как описание. 

да дело не в том как перевести это definition, a в том, к чему его применили smile
ava
baldina | 21.01.2011, 19:09 #
ну ладно, ладно  smile 
определение с реализацией попутали. С++ запутанный язык  smile 
ava
efpies | 22.01.2011, 02:40 #
Всем спасибо за подсказки. smile Многое прояснилось, всё работает, как надо.

Цитата(borisbn @  19.1.2011,  11:54 findReferencedText)


#if !defined( _SOME_CLASS_USING_H_INCLUDED_ )

#define _SOME_CLASS_USING_H_INCLUDED_



class SomeClass;   // Вот так



class SomeClassUsing

{
    public:
        SomeClassUsing(); 
        ~SomeClassUsing();


    private:
        SomeClass * m_someClass;

};

#endif //!defined( _SOME_CLASS_USING_H_INCLUDED_ )


Правда  просто объявить не получится, если SomeClassUsing должен наследовать SomeClass. Нужно подключать SomeClass.h
ava
mes | 22.01.2011, 12:15 #
Цитата(efpies @  22.1.2011,  01:40 findReferencedText)
Правда  просто объявить не получится, если SomeClassUsing должен наследовать SomeClass.

для наследования нужно иметь полное определение наследуемого предка.. т.е. объявления недостаточно
также полное определение нужно для создания/удаления, обращения к составляющим(членам), sizeof, и т.д..
объявления достаточно для использования  ссылки или указателя..

ava
efpies | 23.01.2011, 10:02 #
Возникла такая проблема: некоторые методы считаются неописанными (unresolved external), их нужно описать именно в заголовочном файле. С чем это может быть связано?
ava
efpies | 23.01.2011, 10:18 #
UPD: с inline-функциями такая штука
ava
bsa | 23.01.2011, 10:20 #
efpies, почитай определение встраиваемых функций. Если лень, то в двух словах - тело inline функции должно быть в хидере.
ava
baldina | 24.01.2011, 12:23 #
Цитата(bsa @  23.1.2011,  10:20 findReferencedText)
в двух словах - тело inline функции должно быть в хидере. 

efpies, тут главное не то, что тело inline функции в хидере, а что оно должно быть доступно в момент компиляции.
в .h его помещают именно для этой цели.
ava
semibug | 24.01.2011, 15:00 #
Хочу обратить внимание на фундамент - заголовочные файлы всего лишь программистское соглашение, компилятор (канонический) ничего про них не знает.
Собственно компилирование начинается уже после обработки текста препроцессором, который поставит на место #include текст из соответствующего файла. Не важно какое у него будет расширение и имя, хоть cpp, хоть exe.

Как то раз попалось даже такое извращение - вместо makefile с перечислением сырцов, компилировался один файл, содержащий #include всех остальных файлов проекта.

Присоединяюсь к мнению гуру, один класс - один файл, и, imho, чем он меньше, тем лучше.



ava
wildwolf | 24.01.2011, 22:34 #
я извиняюсь, ребят, помогите пожалуста..
сам изучал с++ .. а тут девушка с задачками подошла, не могу разобраться..
подскажите..
"Дано тело функции main(). Определить что будет выведено на экран в результате выполнения данного кода, и почему (дать пояснения к ответу).
Код:
int n=5;
char * b="0";
printf("%u\n", open("f", O_RONLY));
close(fd);
Примечание: Файла f не существует."
и вторая-
"Пояснить результаты работы программы
#include<unistd.h>
main(){
printf("один/n");
fork();
fork();
printf("два/n");
wait();
printf("три/n");
printf("четыре/n");
}"
или хотя б подскажите где и скать и что за язык..спасибо заранее..
ava
baldina | 25.01.2011, 10:28 #
C++ изучал, говоришь?  :girl_crazy

Добавлено позднее:
язык С. с небольшими (непринципиальными) исправлениями будет компилироваться как С++.

первая программа выведет Очень Большое Число, соотв. максимальному беззнаковому целому на целевой системе. это потомучто open() возвращает int(-1), а спецификация формата вывода - беззнаковая. в 32-битной среде это 4294967295.

вторая программа предназначена для исполнения в POSIX-совместимой среде. *nix например. вызов fork() порождает новый процесс (клон текущего) в точке вызова. wait () приостанавливает текущий процесс, пока один из порожденных процессов не завершится (или не ждет, если порожденных процессов нет). так что теперь можешь сам сообразить что она выведет. 
ava
borisbn | 25.01.2011, 10:55 #
baldina, "+1" :)

надо бы в эту тему скопировать

#inclyde опять же улыбнул
ava
wildwolf | 25.01.2011, 11:13 #
спасиб огромное smile3
изучал, но только поверхносно..
"include" - опечатался=)
ava
Ignat | 25.01.2011, 11:23 #
Цитата(baldina @  25.1.2011,  10:28 findReferencedText)
так что теперь можешь сам сообразить что она выведет.  


Это, кстати, одна из моих любимых задачек. Выведет она не то, что ожидается =)
Чтобы она вывела, что ожидается, нужно ставить flush() после каждого вывода.

ava
wildwolf | 25.01.2011, 11:29 #
а что она выведет? если не секрет)
ava
baldina | 25.01.2011, 11:38 #
Цитата(Ignat @  25.1.2011,  11:23 findReferencedText)
не то, что ожидается

 smile 
что-то мне подсказывает, что от девушки требуют "что ожидается"
Цитата


Пояснить результаты работы программы


интересно, результат приводится?
ava
Ignat | 25.01.2011, 11:41 #
В зависимости от компилятора и платформы:
Цитата


один

два

три

четыре

один

два

три

четыре

один

два

три

четыре

один

два

три

четыре


либо, если сброс буфера будет происходить после каждого вывода
Цитата


один

два

два

два

два

три

четыре

три

четыре

три

четыре

три

четыре


На практике, со вторым поведением сталкивался, кажется, в цигвине.
ava
wildwolf | 25.01.2011, 11:44 #
спасибо!=)
ava
Ignat | 25.01.2011, 11:47 #
Цитата(wildwolf @  25.1.2011,  11:44 findReferencedText)
спасибо!=)

За что?
ни тот, ни другой ответ не гарантирован =)
ava
wildwolf | 25.01.2011, 11:50 #
спасибо, что хоть чем-то помогли..
а там случайно не
"один
один
один
два
три
четыре" ?
ava
Ignat | 25.01.2011, 11:57 #
Цитата(wildwolf @  25.1.2011,  11:50 findReferencedText)
а там случайно не 

Ну это должна быть очень большая случайность, разве что сидеть на изготовку с kill -2, да и то снайпер должен быть знатный.
ava
baldina | 25.01.2011, 12:22 #
wildwolfIgnat, "один" выведется только один раз. в корневом процессе.
ava
Ignat | 25.01.2011, 12:29 #
Цитата(baldina @  25.1.2011,  12:22 findReferencedText)
"один" выведется только один раз. в корневом процессе. 


baldina, на чем проверял?
В своё время проверял на нескольких системах. Результат - процесс форкается вместе с буфферами, следовательно, "один" выведется 4 раза.
ava
baldina | 25.01.2011, 12:32 #
Цитата


если сброс буфера будет происходить после каждого вывода


не успеет. сейчас очень быстрые процессоры ;-)

Добавлено позднее:
Цитата(Ignat @  25.1.2011,  12:29 findReferencedText)
baldina, на чем проверял?

не проверял.
ava
baldina | 25.01.2011, 12:48 #
проверил


Linux 2.6.18-194.26.1.el5 #1 SMP Tue Nov 9 12:54:40 EST 2010 i686 i686 i386 GNU/Linux



один
два
три
четыре
два
три
четыре
два
два
три
четыре
три
четыре
ava
Ignat | 25.01.2011, 12:55 #
Тоже проверил
Linux 2.6.32-27-generic
gcc 4.4.3

Цитата


1

2

2

2

3

4

2

3

4

3

4

3

4



Таки каждый \n приводит к flush. Убираем LF и получаем 1234123412341234.

Добавлено позднее:
Сыплю на голову мусор (пепла нет), про опустошение буффера десятым символом забыл напрочь.
ava
wildwolf | 27.01.2011, 21:43 #
спасиб ребят, оч помогли!=) прокатило! smile   smile  smile 
Зарегистрируйтесь или войдите, чтобы написать.
Фирма дня
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Участники
  Ignat   mes ava  bsa   KaraKum   baldina   semibug   KuMa1104   efpies ava  borisbn   wildwolf
advanced
Отправить