Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по программированию на C/С++

Автор: V0lt
Дата сообщения: 10.06.2012 16:24
Для чего нужен extern при объявлении функции?

Вот пример - http://sourceforge.net/apps/trac/mpc-hc/browser/trunk/src/DSUtil/DSUtil.h
Все функции помечены extern-ом. Этот модуль используется довольно часто.
Автор: karakurt2
Дата сообщения: 10.06.2012 16:40
это говорит о глобальном связывании. досталось в наследство от древних времён. по умолчанию все функции и так являются глобальными, так что на этот модификатор можно не обращать внимания.
Автор: KurkSS
Дата сообщения: 10.06.2012 21:42
А вот у меня вопрос:

я так понимал всегда, что когда мы создаём экземпляр класа, это фактически выделяеться память под запись - где все поля- указатели на память где храняться значения
все методы, дефакто теже поля=ссылки на точки входа в подпрограммы методов.

и жил спокойно, пока не задумался вот над чем. А как быть с полями обьявлеными private!
У класса папа есть приватное поле "дом"
у наследника - класс сын есть своё приватное поле "дом"
методы описаные в класе сын будут обращаться в сыновскую переменную дом, вто время как родительские методы будут обрадаться в родительскую.

так ччто же получаеться - если у меня цепочка из 100 класов скажем, каждый который наследует предыдущего, и в каждом обьявлено прайвит переменая на 4 байта скажем, и метод считывающий это значение.
так что - при создании экземпляра класса100, ему будет выделена область для хранения своей 4 байтовой переменой и плюс ещо 396байт для хранения значений прайвит переменных всех родителей?!?!?!?!
или как там ваще память выделяеться?

Добавлено:
уточняю - во всех 100 класах обьявляю одноименную переменую прайвит! и одноимённый метод для её чтения. но ведь теоретически я могу вызвать родительский метод...тоесть надо чтоб и родительская переменая прайвит существовала.
Получаеться что будет выделена лишняя память если зазря прайвит переменными раскидываться?
Автор: kotlomoy
Дата сообщения: 10.06.2012 23:25
KurkSS
Пример из учебников: если вызвать конструктор производного класса, то будут вызываться и конструкторы всех родительских классов. Так что, получается, экземпляры родительских классов создаются. Причем все поля, независимо от спецификатора доступа.
Автор: V0lt
Дата сообщения: 10.06.2012 23:34
karakurt2

Цитата:
это говорит о глобальном связывании. досталось в наследство от древних времён. по умолчанию все функции и так являются глобальными, так что на этот модификатор можно не обращать внимания.

Спасибо. Теперь хоть и не сильно понятнее, но спокойнее
Автор: panda3
Дата сообщения: 11.06.2012 09:01
V0lt
extern для функций - тип связывания по умолчанию. Т.е. вы можете считать, что перед каждой функцией написано extern, явно его указывать не нужно, но и не мешает. Также как переменные в функциях по умолчанию auto, но никто этого явно обычно не пишет. Чтобы функция не была extern, ей можно явно указать тип связывания static, тогда функция не будет доступна для линкера и ее нельзя будет вызывать из других модулей.
В зависимости от реализации, фунции inline могут иметь тип связывания по умолчанию static, вот для них необходимо явно указывать extern, чтобы они были доступны из других модулей.
Автор: KurkSS
Дата сообщения: 11.06.2012 09:10
ПОДКЛЮЧАЕМСЯ ГУРУ!!!!


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


мысль интересная. но!!!
но с трудом вериться что при иерархии в 10-15 класов, а в библиотеках визуальных компонентов оно имено так и бывает, будет столько всего создаваться...

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

ПРошу всех кто может помочь разобраться. Как выделяеться память при создании обьекта, где храняться прайвит поля родительских класов???
Автор: panda3
Дата сообщения: 11.06.2012 10:07
Конструкторы не выделяют память. Память выделяется либо в сегменте данных (для глобальных объектов), в сегменте стека (для автоматических объектов) - ее выделяет ОС при загрузке программы. Либо в динамической памяти оператором new. Конструктор инициализирует уже выделенную память. Private поля хранятся там же, где и все остальные. Private - это указание для компилятора, разрешать доступ к полю или нет. На хранение данных и доступ к ним при выполнении программы никакого влияния не оказывает.
Автор: kotlomoy
Дата сообщения: 11.06.2012 14:57
KurkSS
panda3 правильно сказал.
Конструкторы не выделяют память под переменные. Когда конструктор класса вызывается, память под объект этого класса уже выделена.
Private - это спецификатор доступа. К памяти это не имеет отношения.

При иерархии 10-15 классов будут создаваться все объекты этих классов, а как иначе? Иначе ничего работать не будет.
Автор: KurkSS
Дата сообщения: 11.06.2012 17:36

Цитата:
При иерархии 10-15 классов будут создаваться все объекты этих классов, а как иначе? Иначе ничего работать не будет.
так вот в этом то и смонение

класы это описание поведения, наследник доопиывает наследуемого. тоесть поидее в дочернем щитай перечислено всё что в папе плюс ещо в себе...смысл зожадвать два класса на основе одного описания.
Автор: kotlomoy
Дата сообщения: 11.06.2012 20:44
KurkSS
Правильно. Наследник содержит в себе свои поля плюс поля всех родителей.
В случае, если в наследнике объявлена переменная, одноименная переменной родительского класса, создаются ОБЕ эти переменные.
Т.е., например, если в родительском классе parent_t объявлена переменная a, а в классе-наследнике child_t тоже объявлена переменная a, то экземпляр класса child_t будет содержать обе эти переменные.

Пример:

[more=КОД ПРОГРАММЫ]
Код: class parent_t
    {
    public:
        char a;
    };


class child_t : public parent_t
    {
    public:
        char a;
        char b;

        void setBaseA( char a );
    };


void child_t::setBaseA( char a )
    {
    parent_t::a = a;
    };


int main()
    {
    parent_t A;
    A.a = 1;

    child_t B;
    B.a = 2;
    B.b = 3;
    B.setBaseA( 4 );
    };
Автор: stasnewar
Дата сообщения: 15.06.2012 02:28
Здравствуйте.

У меня вопрос. Как работает конструкция switch-case, допустим есть такой код:

while(1) {
switch (state) {
case 1:
state = 2;
k = 1;
break;
case 2:
k = 2;
break;
}
}

какое значение примет переменная k за первый проход цикла? 1 или 2?
т.е. впрос звучит так, switch-case делает проверку один раз за проход?
Автор: akaGM
Дата сообщения: 15.06.2012 02:42
stasnewar

Цитата:
какое значение примет переменная k за первый проход цикла? 1 или 2?

ты не забыл инициализировать state?
state = 1; так будет k=1
state = 2; так будет k=2


Цитата:
т.е. впрос звучит так, switch-case делает проверку один раз за проход?

уже зависит от того где ты решишь поставить отпрыги

хоть так:

switch (state) {
case 1:
case 3:
case 5:
case 7:
k = 1;
break;
case 2:
k = 2;
break;
}
Автор: ne_viens
Дата сообщения: 15.06.2012 10:28

Цитата:

...
какое значение примет переменная k за первый проход цикла? 1 или 2?
т.е. впрос звучит так, switch-case делает проверку один раз за проход?


Сначала выполнится case потом state=2, значит к=1

Вместо while(1) {} лучше пользоватся for(;;) {} , таким образом экономится 3 инструкции машинного кода. И одна буква c кода тоже
Автор: cp58
Дата сообщения: 15.06.2012 11:05
ne_viens

Цитата:
Вместо while(1) {} лучше пользоватся for(;;) {} , таким образом экономится 3 инструкции машинного кода.

Сами придумали?
stasnewar
break здесь неспроста.
Автор: akaGM
Дата сообщения: 15.06.2012 11:09
ne_viens
cp58


infiniteloop:
...
goto infiniteloop;

:)

stasnewar
и не забывай, что у switch'a есть дефолтная ветка.
при старте с state=100 ты вообще ни фига не получишь, вернее, получишь то что я написал чуть выше...
Автор: ne_viens
Дата сообщения: 15.06.2012 12:40

Цитата:
Сами придумали?
...


Посмотрел.
При неоптимизированном коде это всегда так, если врубить /Ox , то иногда, если петля длинная.
Автор: stasnewar
Дата сообщения: 15.06.2012 12:45
akaGM

Цитата:
ты не забыл инициализировать state?


Забыл, писал на скорую руку. Да, сначала state=1, следует k=1 за первый проход.
Автор: akaGM
Дата сообщения: 15.06.2012 12:53
stasnewar

Код: switch (state) {
case 1:
k = 1;
case 2:
k = 2;
case 3:
k = 3;
case 4:
k = 4;}
Автор: blaro
Дата сообщения: 15.06.2012 19:54
Добрый вечер. У меня такой вопрос: как написать функцию которая принимает указатель на объект и выделяет для него в памяти место и так же возвращала указатель на него? Для наглядности приведу приме

Код:
int *a;
char *b
float *c

//
... mymalloc(a)
{
return (a)malloc(100*sizeof(a));
}
//В конце должен быть массив целых чисел [0][1][2]...[100]
//Если передать char то будет массив букв [0][1][2]...[100]
Автор: cp58
Дата сообщения: 15.06.2012 20:13
blaro

Цитата:
void* CREATE_TREE(void* t)
{
return (t)calloc(sizeof(t),1);
}

Смысл передавать указатель, если функция выделения памяти из кучи все равно вернет новый?
И что значит (t), если это переменная, а не тип?
int *t; это просто объявление переменной, t содержит лишь мусор, оставшийся в стеке(если объявлено внутри функции). Затем этой перменной уже передается адрес на ячейку памяти размером с sizeof(type) (или начальной ячейке, если это массив).
Автор: blaro
Дата сообщения: 15.06.2012 20:19
Ну а как тогда написать общую функцию которая делает так как мне надо?
Автор: cp58
Дата сообщения: 15.06.2012 20:28
blaro
Чем стандартная функция не угодила?(malloc,calloc...)
sizeof в любом случае работает во время компиляции.
Автор: kotlomoy
Дата сообщения: 16.06.2012 00:50
ne_viens

Цитата:
Вместо while(1) {} лучше пользоватся for(;;) {} , таким образом экономится 3 инструкции машинного кода. И одна буква c кода тоже

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

blaro
Прочитайте хотя бы, что такое указатель, и что делают sizeof и malloc/calloc.
Автор: ItsJustMe
Дата сообщения: 16.06.2012 01:00
blaro

Цитата:
Ну а как тогда написать общую функцию которая делает так как мне надо?

ну так и напиши, кто ж тебе мешает?

Код: template <class T>
T* Talloc(T* &t)
{
return t = new T();
}
Автор: cp58
Дата сообщения: 16.06.2012 03:24
ItsJustMe

Цитата:
template <class T>
T* Talloc(T* &t)
{
return t = new T();
}

Используется C, судя по примеру, а не C++.
Да и обертка по своей сути бесполезна.
Автор: kotlomoy
Дата сообщения: 16.06.2012 14:39
ItsJustMe

Цитата:
Не знал, что профессиональные программисты имеют в этом случае продпочтение, и склоняются к первому варианту По мне и так и так кошерно Но мне простительно, я - не профессиональный.

Хорошо, когда сидишь в свое программе и пишешь как хочешь. А вот когда одну программу много людей пишет, постоянно приходится с чужим текстом работать. И когда все пишут как им захочется, то большую часть времени сидишь разбираешь чужие каракули и поминаешь авторов добрым словом.
Так что, если нужно повысить производительность - пишите хороший читабельный текст, оформляйте его. И меньше икаться вам будет.
Автор: akaGM
Дата сообщения: 16.06.2012 17:49
а зачем с чужим кодом работать, ошибки вылавливать?
хотя я-то как раз за читабельность и структурированность кода...
хотя бы ради самого себя через n ле т:)
Автор: karakurt2
Дата сообщения: 16.06.2012 18:32
akaGM, через n лет смотришь на код и думаешь, как же я мог такое написать
Автор: kotlomoy
Дата сообщения: 16.06.2012 18:45
akaGM

Цитата:
а зачем с чужим кодом работать, ошибки вылавливать?

Ошибки вылавливать, дописывать, переписывать

Страницы: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193

Предыдущая тема: не знаю как назвать тему :-)


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.