Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Исключения и профилактика утечек памяти. 
:(
    Опции темы
makavelly
Дата 9.4.2012, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 26.3.2008

Репутация: нет
Всего: нет



На c++ не пишу, но возникла необходимость. Допустим, есть такой код:
Код

  MyImporter * importer = new MyImporter();
  myObject = importer->ReadFile(sourceFileName);
  
  if ( myObject == NULL )
    ThrowException("Failed to import object!");

  delete importer;

Как я понимаю, при возникновении исключительной ситуации (5-я строка), подчистить за собой не получится. Как обычно в c++ решают такие ситуации? Например, в Delphi это можно оформить как try - finally - end. Разместив удаление объекта в finally ... end можно получить почти 100% гарантию уничтожения объекта. 
И еще вопрос... Есть ли в MS VC Express 2008 какой-нибудь механизм, позволяющий отслеживать утечки памяти?
PM MAIL   Вверх
Amp
Дата 9.4.2012, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 886
Регистрация: 17.2.2009

Репутация: нет
Всего: 17



Создать объект на стэке, использовать умные указатели,  измазать код в BOOST_SCOPE_EXIT/BOOST_SCOPE_EXIT_END и т.п.
PM MAIL   Вверх
boostcoder
Дата 9.4.2012, 17:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



Цитата(makavelly @  9.4.2012,  16:56 Найти цитируемый пост)
Как обычно в c++ решают такие ситуации?

RAII.

тогда код записывается так:
Код

  boost::shared_ptr<MyImporter> importer(new MyImporter);
  myObject = importer->ReadFile(sourceFileName);
  
  if ( myObject == NULL )
    ThrowException("Failed to import object!");


PM WWW   Вверх
makavelly
Дата 9.4.2012, 21:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 26.3.2008

Репутация: нет
Всего: нет



Я наслышан о boost - массивный инструмент, можно обойтись без него?
Почитал про RAII, возникло несколько вопросов. C++ поддерживает этот принцип?
Хотелось бы еще уточнить по поводу области видимости. Пример функции (видел нечто подобное в чужом коде):
Код

void DoSomeProcessing(const char * fileName)
{
    MyImporter importer;
    myObject = importer.ReadFile(fileName);

    if ( myObject == NULL )
        ThrowException("Failed to import object!");

    /*  do something with myObject  */

}

Получается, что когда заканчивается выполнение DoSomeProcessing() importer выходит из области видимости и ресурсы будут освобождены? Если эта функция будет вызвана повторно, мы будем иметь дело с новым объектом importer? А если DoSomeProcessing() будет принадлежать классу? 
Вопросы, конечно, кажутся наивными, но как по мне, C++ коварен.
PM MAIL   Вверх
azesmcar
Дата 9.4.2012, 21:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата(makavelly @  9.4.2012,  21:00 Найти цитируемый пост)
Почитал про RAII, возникло несколько вопросов. C++ поддерживает этот принцип?

Поддерживает. Из стандартных средств можно использовать std::auto_ptr

Цитата(boostcoder @  9.4.2012,  17:03 Найти цитируемый пост)
boost::shared_ptr<MyImporter> importer(new MyImporter);

применительно к данной ситуации shared_ptr - overkill smile 
Цитата(makavelly @  9.4.2012,  21:00 Найти цитируемый пост)
Получается, что когда заканчивается выполнение DoSomeProcessing() importer выходит из области видимости и ресурсы будут освобождены? Если эта функция будет вызвана повторно, мы будем иметь дело с новым объектом importer?

Да.

Цитата(makavelly @  9.4.2012,  21:00 Найти цитируемый пост)
А если DoSomeProcessing() будет принадлежать классу? 

Без разницы.

Это сообщение отредактировал(а) azesmcar - 9.4.2012, 21:08
PM   Вверх
makavelly
Дата 9.4.2012, 21:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 26.3.2008

Репутация: нет
Всего: нет



Благодарю за ответы, ситуация начинает понемногу проясняться.
Еще один вопрос. Допустим, я хочу, что бы объект класса MyImporter являлся членом моего класса, который осуществляет некоторые действия над ним. Я хочу, чтобы экземпляр MyImporter'a существовал все время жизни экземпляра класса-обертки. Как я понимаю, для этого следует прописать такое объявление в объявлении класса-обертки 
Код

MyImporter * importer;

В конструкторе:
Код

importer = new MyImporter();

В деструкторе:
Код

delete importer;


PM MAIL   Вверх
azesmcar
Дата 9.4.2012, 21:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



makavelly

Можно и так
Код

class X
{
public:
   useImporter() {
      importer.import();
   }
private:
   MyImporter importer;
};

PM   Вверх
makavelly
Дата 9.4.2012, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 26.3.2008

Репутация: нет
Всего: нет



Цитата(azesmcar @ 9.4.2012,  21:25)
makavelly

Можно и так
Код

class X
{
public:
   useImporter() {
      importer.import();
   }
private:
   MyImporter importer;
};

Т.е. получается, сам факт объявления в классе
Код

MyImporter importer;

уже создает объект importer... и как я догадываюсь, во время создания экземпляра класса X. Следует ли отсюда, что при уничтожении экземпляра класса X автоматически будут освобождены ресурсы, выделенные под importer? 
PM MAIL   Вверх
azesmcar
Дата 9.4.2012, 21:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата(makavelly @  9.4.2012,  21:37 Найти цитируемый пост)
и как я догадываюсь, во время создания экземпляра класса X

 smile 

Цитата(makavelly @  9.4.2012,  21:37 Найти цитируемый пост)
Следует ли отсюда, что при уничтожении экземпляра класса X автоматически будут освобождены ресурсы, выделенные под importer?  

 smile 
PM   Вверх
boostcoder
Дата 9.4.2012, 22:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



Цитата(azesmcar @  9.4.2012,  21:03 Найти цитируемый пост)
применительно к данной ситуации shared_ptr - overkill

ну да. скопеда достаточно.

PM WWW   Вверх
borisbn
Дата 10.4.2012, 06:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



makavelly, и ещё один момент. Если в заголовочный файл класса-обёртки включить объект MyImporter, а не указатель на него
Код

MyImporter m_importer; // <-- так
MyImporter *m_importer; // <-- а не так

то в этот же заголовочный файл придётся включить и h-ник с объявлением MyImporter (например "importer.h"). При включении h-ника класса-обёртки в нескольких cpp-шниках "importer.h" будет компилироваться несколько раз, что увеличивает время компиляции.
Если же ты включишь в класс-обёртку указатель, то "importer.h" достаточно включить только в cpp-нике класса обёртки, а в h-нике предобъявить MyImporter
Код

class MyImporter; // предобъявление

class Wrapper {
MyImporter * my_importer;
...
};


Это сообщение отредактировал(а) borisbn - 10.4.2012, 06:42


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
makavelly
Дата 10.4.2012, 10:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 26.3.2008

Репутация: нет
Всего: нет



borisbn, я видел вот такую конструкцию в *.h:
Код

#ifndef MY_H
#define MY_H

    ...
    ...
    ...

#endif

Может это для таких случаев

Хотелось бы еще уточнить. В некоторых исходниках можно встретить подобные объявления:
Код

Object mObject;
Object m_Object;

Достаточно часто такое встречается. Какая смысловая нагрузка у префикса "m"?
PM MAIL   Вверх
azesmcar
Дата 10.4.2012, 10:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата(makavelly @  10.4.2012,  10:51 Найти цитируемый пост)
borisbn, я видел вот такую конструкцию в *.h:

Это для того, чтобы при множественном включении заголовочного файла не возникало ошибок компиляции.
Еще часто используется #pragma once, который не стандартен, но тем не менее поддерживается очень многими компиляторами.

Цитата(makavelly @  10.4.2012,  10:51 Найти цитируемый пост)
Достаточно часто такое встречается. Какая смысловая нагрузка у префикса "m"? 

Указывает на то, что это member variable. Это так называемая венгерская нотация.

Это сообщение отредактировал(а) azesmcar - 10.4.2012, 10:56
PM   Вверх
borisbn
Дата 10.4.2012, 10:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(makavelly @  10.4.2012,  10:51 Найти цитируемый пост)
Может это для таких случаев

нет. если h-ник включен в двух разных единицах трансляции (проще - в 2-х cpp-шниках), то он будет компилироваться дважды, несмотря на эти, т.н. guard'ы. А эти guird'ы нужны, чтобы в такой ситуации
Код

// 1.h
class X {};
// 2.h
#include "1.h"
// 3.h
#include "1.h"
#include "2.h"

код из 1.h не повторялся. иначе получится 2 описания класса X.

Цитата(makavelly @  10.4.2012,  10:51 Найти цитируемый пост)
. Какая смысловая нагрузка у префикса "m"? 

member of class


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
makavelly
Дата 10.4.2012, 18:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 26.3.2008

Репутация: нет
Всего: нет



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

struct MyResultA
{
    unsigned int resultCode;    
    unsigned int elapsedTime;    
};

Вопрос: чревато ли возвращать адрес локальной переменной (меня это очень смущает)? Например:
Код

MYLIB_API MyResultA * DoSomethingA( ... )
{
    MyResultA ret = {0, 0};

               /*  processin data here  */

    return &ret;
}

PM MAIL   Вверх
borisbn
Дата 11.4.2012, 08:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(makavelly @  10.4.2012,  18:18 Найти цитируемый пост)
 чревато ли возвращать адрес локальной переменной (меня это очень смущает)

Это должно не "смущать", а "орать благим матом", что такого делать нельзя. Хоть в dll-ке, хоть в исходниках.
Есть сразу несколько вариантов:
1) вернуть структуру по значению
Код

MyResultA DoSomethingA(...) {
    MyResultA ret = {0,0};

    return ret;
}
// вызов
MyResultA res = DoSomethingA(...);

2) Передать в функцию ссылку на структуру и заполнить её внутри функции (я бы выбрал этот вариант) :
Код

void DoSomethingA( MyResultA & result ) {

    result.resultCode = ...;
    result.elapsedTime = ...;
}
// вызов
MyResultA res;
DoSomethingA( res );

3) обойтись вообще без структуры:
Код

int DoSomethingA( int & elapsedTime ) {

    elapsedTime = ...;
    return код результата;
}

// вызов
int elapsedTime;
int resultCode = DoSomethingA( elapsedTime );



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
mes
Дата 11.4.2012, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(makavelly @  10.4.2012,  17:18 Найти цитируемый пост)
: чревато ли возвращать адрес локальной переменной


а возмущениям компилятора не верите ?!


--------------------
PM MAIL WWW   Вверх
makavelly
Дата 12.4.2012, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 26.3.2008

Репутация: нет
Всего: нет



borisbn, да, вариант #2 - самое оно. 
Еще один вопрос сформировался у меня. В C# есть очень удобные классы BinaryWriter, MemoryStream, FileStream и пр., при помощи которых легко и просто осуществляется ввод\вывод, работа с данными в памяти. Есть ли в C++ что-либо похожее на MemoryStream? Может какие-нибудь легковесные библиотеки?
PM MAIL   Вверх
ller
Дата 12.4.2012, 19:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 325
Регистрация: 4.8.2008
Где: г. Таганрог

Репутация: 2
Всего: 4



есть std::stringstream потоковый ввод вывод из/в строки
PM MAIL   Вверх
makavelly
Дата 13.4.2012, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 26.3.2008

Репутация: нет
Всего: нет



Хотелось бы еще уточнить по поводу передачи ссылки на экземпляр класса как параметр функции. 

Если передать следующим образом:
Код

void MyFunc(MyClass val)
{
    ...
}

то что передастся в функцию? Копия экземпляра?

Если передавать вот так:
Код

void MyFunc(MyClass & val)
{
    ...
}

то, как я понимаю, я получаю доступ к экземпляру по ссылке.

А если вот так:
Код

void MyFunc(const MyClass & val){   ...  }

или так:
Код

void MyFunc(const MyClass val){  ...  }

Какие здесь работают правила? 
Может быть кто-нибудь знает ссылку на толковую статью по теме?
PM MAIL   Вверх
borisbn
Дата 13.4.2012, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(makavelly @  13.4.2012,  17:00 Найти цитируемый пост)
то что передастся в функцию? Копия экземпляра?

да
Цитата(makavelly @  13.4.2012,  17:00 Найти цитируемый пост)
то, как я понимаю, я получаю доступ к экземпляру по ссылке.

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

MyClass someObj;
void MyFunc( MyClass & val ) {
    val.field = 0; // идентично тому, что написать someObj.field = 0; 
            // при условии, что вызов будет такой MyFunc( someObj );
}


Цитата(makavelly @  13.4.2012,  17:00 Найти цитируемый пост)
А если вот так:
Код
void MyFunc(const MyClass & val){   ...  }

val тоже будет являться "алиасом", но в него нельзя будет ничего записать и вызывать можно будет только функции класса MyClass, помеченные как const

Цитата(makavelly @  13.4.2012,  17:00 Найти цитируемый пост)
или так:
Код
void MyFunc(const MyClass val){  ...  }

В это случае будет передана копия экземпляра, у которой также нельзя будет ничего записать и вызывать можно будет только функции класса MyClass, помеченные как const


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
makavelly
Дата 13.4.2012, 20:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 26.3.2008

Репутация: нет
Всего: нет



Т.е. в общих чертах получается: если надо просто извлечь данные из экземпляра класса, то
Код

void MyFunc(const MyClass & val){  ...  }

Если надо изменить передаваемый объект, то
Код

void MyFunc(MyClass & val){  ...  }

Спасибо за ответы, хорошо, когда есть у кого уточнить=)
PM MAIL   Вверх
makavelly
Дата 16.4.2012, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 26.3.2008

Репутация: нет
Всего: нет



Хотелось бы еще поинтересоваться по поводу исключений. Есть класс, который будет содержать данные исключения (например код ошибки, человеческое описание, что-либо еще). Как я понимаю возбуждать такое исключение надо так:
Код

void ThrowException( ... )
{
    throw MyExceptionClass( ... );
}

А ловить как-то так:
Код

try
{
    // something dangerous
}
catch (MyExceptionClass ex)
{
    // processing according ex data...
}

Когда объект исключения будет уничтожен? Я полагаю, что после выхода из
Код

catch (MyExceptionClass ex)
{
    // processing according ex data...
}

Верно? Т.е., если объект исключения предоставляет доступ к тексту ошибки через указатель на char, я должен скопировать данные с этого указателя в блоке catch (MyExceptionClass ex) { ... } ?
PM MAIL   Вверх
azesmcar
Дата 16.4.2012, 18:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата(makavelly @  16.4.2012,  17:12 Найти цитируемый пост)
А ловить как-то так:

Как-то, но не так smile 

Цитата

catch (MyExceptionClass& ex)

исключения лучше ловить по ссылке.

Цитата(makavelly @  16.4.2012,  17:12 Найти цитируемый пост)
Когда объект исключения будет уничтожен?

Цитата

The memory for the temporary copy of the exception being thrown is allocated in an unspecified way,
except as noted in 3.7.3.1. The temporary persists as long as there is a handler being executed for that
exception. In particular, if a handler exits by executing a throw; statement, that passes control to another
handler for the same exception, so the temporary remains. When the last handler being executed for the
exception exits by any means other than throw; the temporary object is destroyed and the implementation
may deallocate the memory for the temporary object; any such deallocation is done in an unspecified way.
The destruction occurs immediately after the destruction of the object declared in the exception-declaration
in the handler.


Это сообщение отредактировал(а) azesmcar - 16.4.2012, 18:34
PM   Вверх
baldina
Дата 16.4.2012, 18:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



ловить лучше ссылку
Код

catch (MyExceptionClass& ex)

во избежание лишнего копирования
жить будет до окончания блока catch, так что внутри него можно спокойно пользоваться объектом.

Добавлено через 2 минуты и 5 секунд
azesmcar уже ответил...
ну тогда вот краткая иллюстрация
http://codepad.org/oqkk0CiV
PM MAIL   Вверх
borisbn
Дата 16.4.2012, 18:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



makavelly, это всё довольно просто проверяется - http://liveworkspace.org/code/cde774c60990...0b02c871181bb3b
кстати, пока изучаешь, вози этот классик для всяческих проверок... если пишешь на MSVC, то замени все __PRETTY_FUNCTION__ на __FUNCSIG__


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
makavelly
Дата 19.4.2012, 18:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 26.3.2008

Репутация: нет
Всего: нет



До этого достаточно долго работал с Delphi, все там как-то проще, труднее ошибиться. Это так, к слову.
Сейчас добрался до реализации класса, хочеться сделать все грамотно. 

Вот первый вопрос. Есть класс который, например, пишет данные в файл. Пусть этот класс предоставляет данные о версии файлов, генерируемых с его помощью. Например:
Код

class MyExporter
{
private:
    static const unsigned int myFileMajorVersion = 1;
    static const unsigned int myFileMinorVersion = 0;

              static void ThrowException();

public:
    static unsigned int GetFileMajorVersion();
    static unsigned int GetFileMinorVersion();

};

Верно ли, что функции GetFileMajorVersion() и GetFileMinorVersion() я объявляю как static? Ведь, по идее, их можно вызывать без создания экземпляра класса. Есть ли смысл делать функцию ThrowException() тоже static?

Еще вопрос. Иногда функции помечаются как const, типа
Код

void DoSomething() const;

В каких случаях принято использовать такие пометки? Когда действия внутри функции не затрагивают переменных класса? Какое тогда отличие от static?


PM MAIL   Вверх
borisbn
Дата 20.4.2012, 08:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(makavelly @  19.4.2012,  18:34 Найти цитируемый пост)
Верно ли, что функции GetFileMajorVersion() и GetFileMinorVersion() я объявляю как static?

 smile 

Цитата(makavelly @  19.4.2012,  18:34 Найти цитируемый пост)
Ведь, по идее, их можно вызывать без создания экземпляра класса. 

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

Цитата(makavelly @  19.4.2012,  18:34 Найти цитируемый пост)
В каких случаях принято использовать такие пометки? Когда действия внутри функции не затрагивают переменных класса? Какое тогда отличие от static?

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

static же функции не имеют доступа к членам и методам класса. Они практически не отличаются от обычных функций вне класса.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
makavelly
Дата 20.4.2012, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 26.3.2008

Репутация: нет
Всего: нет



Цитата

Действия const'овой функции не могут изменять переменные класса, а читать их они могут.

Если переменные простых типов (int, unsigned int ...), то понятно. А если, например, в качестве переменной выступает указатель на экземпляр класса. Из такой функции нельзя произвести действия, изменяющие что-либо в этом экземпляре? Вот заставить такой указатель указывать на что-либо иное из такой ф-ции, как понимаю, нельзя.

А есть смысл помечать как static функции вне классов? Я, кажется, подобное видел, хотя могу и ошибаться. 

PM MAIL   Вверх
borisbn
Дата 20.4.2012, 12:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(makavelly @  20.4.2012,  11:42 Найти цитируемый пост)
 Из такой функции нельзя произвести действия, изменяющие что-либо в этом экземпляре?

 smile 
Т.е. опять же, можно вызывать только const'овые методы того ("дочернего") класса. И читать открытые свойства.

Цитата(makavelly @  20.4.2012,  11:42 Найти цитируемый пост)
А есть смысл помечать как static функции вне классов?

у свободных функций (вне класса) пометка static значит совсем иное - это говорит о том, что эта функция видна только в этой единице трансляции (в этом cpp-шнике), и сделать на неё extern из другого cpp-шника нельзя.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1264 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.