Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.05.2009, 10:24   #1
Qousio
Пользователь
 
Аватар для Qousio
 
Регистрация: 02.05.2009
Сообщений: 27
По умолчанию Классы vs. функции (вопрос, а не холивар)

Здравствуйте.

В обьектном аспекте С++ я совсем новичок, ибо раньше обьектные языки не использовал. Сейчас поэксперементировал с классами, конструкторами и.т.д. Возник вопрос, а зачем собственно всё это надо?
Все, что можно сделать в классе, можно сделать в функции и скорее всего это займет меньше кода... Вот пример из моей книги:

Код:
class Vehicle {
public:
int passengers;
int fuelcap;
int mpg;
}
Дальше обьявляется
Код:
Vehicle minivan;
minivan.passengers = 7;
minivan.fuelcap = 12;
minivan.mpg = 4;
В целом, это заняло 10 строк кода, что нам мешало просто обьявить:
int minivan_passengers = 7 и.т.д. ? Тогда мы экономим 7 строк кода.

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

Ну и немного offtopic вопрос, который меня вечно мучает. Он не совсем связан с С++, скорее связан со всеми структурными языками.

Когда следует использовать глобальные переменные, а когда нет? Вот к примеру:

Код:
#include <iostream>
using namespace std;

int func1(int &b);

int main() {
int b = 1;
func1(b); //Тут изменяется -локальная- переменная b
cout << func1(b) << "   " << b; //Первое число, a+b (причём b уже измененная) и число b, также измененная
cin >> b; //Просто для паузы
return 0;
}

int func1(int &b) {
int a = 2;
b++;
return a+b;
}
Тут можно занести b как глобальную переменную, результат будет такой же... Какой метод эффективнее и какой наиболее наглядный (какой читать проще кодеру)
Чем более читаете, не размышляя, тем более, уверяетесь, что много знаете, а чем более размышляете, читая, тем яснее видите, что знаете еще очень мало.

Последний раз редактировалось Qousio; 21.05.2009 в 10:27.
Qousio вне форума Ответить с цитированием
Старый 21.05.2009, 13:23   #2
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,088
По умолчанию

Цитата:
Сообщение от Qousio Посмотреть сообщение
В обьектном аспекте С++ я совсем новичок, ибо раньше обьектные языки не использовал. Сейчас поэксперементировал с классами, конструкторами и.т.д. Возник вопрос, а зачем собственно всё это надо?
Классы позволяют объединить данные и операции, производимые над ними. При грамотном использовании хорошая штука. Читаются программы легче. В общем ни словом сказать, ни пером описать. Только неправильное использование наоборот ситуацию усугубляет.
Цитата:
Сообщение от Qousio Посмотреть сообщение
Все, что можно сделать в классе, можно сделать в функции и скорее всего это займет меньше кода...
Хорошо. Сделайте массив аналогичных Vehicle данных без классов, запретите запись в passengers отрицательных значений. Ну и, думаю, хватит пока.
Вот мой вариант с классами:
Код:
class Vehicle {
private:
  int m_passengers;
  int m_fuelcap;
  int m_mpg;
public:
  int getPassengers() const
  {
    return m_passengers;
  }
  int getFuelCap() const
  {
    return m_fuelcap;
  }
  int getMpg() const
  {
    return m_mpg;
  }
public:
  void setPassengers(int new_value)
  {
    if (new_value < 0)
      return;
    m_passengers = new_value;
  }
  ...
}
Не правда ли ужасно громоздко выглядит?
Но теперь посмотрим на использование этого класса:
Код:
Vehicle v[10]; // массив транспортных средств
...
v[2].setPassengers(5);
v[2].setPassengers(-10); // пытаемся установить отрицательное число пассажиров
v[2].getPassengers(); // Вернёт число 5, т.к. -10 не записалось
Попробуйте сделать это без классов и посмотрим насколько меньше строк будет у Вас и чей код будет хуже читаться.
Цитата:
Сообщение от Qousio Посмотреть сообщение
Когда следует использовать глобальные переменные, а когда нет?
Глобальные переменные - зло. Константы глобальные - это еще куда ни шло, хотя и их в идеале нужно разносить по соответствующим пространствам имён (namespace). Допустим две функции изменяют одну и ту же глобальную переменную. Вы решили эти функции вызвать из разных потоков и выполняются они параллельно. Что из этого получится?
Цитата:
Сообщение от Qousio Посмотреть сообщение
Тут можно занести b как глобальную переменную, результат будет такой же... Какой метод эффективнее и какой наиболее наглядный (какой читать проще кодеру)
Вариант с глобальными переменные для меня не нагляден. Так вот сразу я не могу определить кем и где значение переменной изменяется. Нужно "путешествовать" по всему коду в поисках "истины". Да и легко попасть на одинаковые имена локальных/глобальных переменных и поменять не то значение.
Например, была глобальная переменная и функция:
Код:
int a; // глобальная переменная
...
int foo(int b)
{
  int a; // локальная переменная
  a = b * 2; // изменение локальной переменной
  return a;
}
Потом мы решили переименовать локальную переменную и назвали её "c", а из-за невнимательности забыли в остальных местах так же изменить "a" на "c". В итоге компилятор код сгенерирует, но будет "портиться" глобальная переменная, а найти такую ошибку в крупном проекте очень сложно.
pu4koff вне форума Ответить с цитированием
Старый 21.05.2009, 13:40   #3
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
Классы позволяют объединить данные и операции, производимые над ними
Я бы еще добавил что классы позволяют указать какие функции доступны а какие нет (public private), таким образом отсеивая ненужную кучу функций.

Нет, ООП чтука полезная.
Цитата:
Глобальные переменные - зло. Константы глобальные - это еще куда ни шло
Куда бы зло ни шло...
Нет Глобалы это не зло, а всего лишь искушение злоупотребления.
Переменные нужно определять для того участка кода, где конкретная переменная нужна. Если она нужна для всей программы, например как в Делфи переменные типа TForm то тут уж локализовывать по функциям ее не стоит
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 21.05.2009, 17:14   #4
Qousio
Пользователь
 
Аватар для Qousio
 
Регистрация: 02.05.2009
Сообщений: 27
По умолчанию

Понятно, буду пристальнее приглядыватся к ООП. А насчёт глобальных переменных, если они такое зло, зачем же их оставили в С++ ? Я вот читал статью одного из людей принимавших нынешний стандарт С++, там был пункт про команду Goto. Какое бы оно зло не было и как бы оно не нарушало структуру кода, его оставили т.к. иногда это просто очень полезная штука. Например:

Код:
for(...) {
for(...) {
while(...) {
if(...) goto error1;
,
,
,
}
}
}
error:
cout < "error1\n";
Можно конечно в каждый из цикл добавить оператор типа (|| error = true), но опять же возникнет немало путаницы из за этих многочисленных || error в коде, особенно если есть сообщение о нескольких ошибках.

Что-то я отошёл от темы, вообщем допустим у меня в коде глобальная константа g = 9.8 которая используется во многих функцих, что-же тут может быть такого злого?
Чем более читаете, не размышляя, тем более, уверяетесь, что много знаете, а чем более размышляете, читая, тем яснее видите, что знаете еще очень мало.
Qousio вне форума Ответить с цитированием
Старый 21.05.2009, 17:36   #5
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,088
По умолчанию

Цитата:
Сообщение от Qousio Посмотреть сообщение
А насчёт глобальных переменных, если они такое зло, зачем же их оставили в С++ ?
С++ до сих пор оставляют полностью совместимым с Си. Чтобы сишные программы без труда компилировались компиляторами С++
Да и вообще С/С++ - это очень демократичные языки. Никому ничего не навязывают. Пишите как хотите, как говорится
Цитата:
Сообщение от Qousio Посмотреть сообщение
Я вот читал статью одного из людей принимавших нынешний стандарт С++, там был пункт про команду Goto. Какое бы оно зло не было и как бы оно не нарушало структуру кода, его оставили т.к. иногда это просто очень полезная штука. Например:

Код:
for(...) {
for(...) {
while(...) {
if(...) goto error1;
,
,
,
}
}
}
error:
cout < "error1\n";
Можно конечно в каждый из цикл добавить оператор типа (|| error = true), но опять же возникнет немало путаницы из за этих многочисленных || error в коде, особенно если есть сообщение о нескольких ошибках.
Я посмотрю что Вы будете делать, если забудете в случае успеха "перепрыгнуть" через все эти метки. А то ведь навыдаёт программа пользователю:
error1
erro2
error3
...
Хотя наоборот никаких ошибок не возникло.
Нравится goto - изучайте ассемблер, а на языках класса С/С++ этому механизму есть куча альтернатив на любой вкус:
Можно использовать механизм исключений:
Код:
try
{
  while (...)
  {
    if (...) throw 1;
    else if (...) throw "трям"
  }
}
catch (int i)
{
  cout << "error1\n";
}
catch (char const *str)
{
  cout << "error2\n";
}
Или можно так:
Код:
inline void error1()
{
  cout << "error1\n";
}
...
while (...)
{
  if (...)
  {
    error1();
    break;
  }
}
...
Цитата:
Сообщение от Qousio Посмотреть сообщение
Что-то я отошёл от темы, вообщем допустим у меня в коде глобальная константа g = 9.8 которая используется во многих функцих, что-же тут может быть такого злого?
Про константы я вообще-то написал, что ничего плохого в этом нет. Переменные глобальные - зло, а константы - это норма вроде как. Только лучше объявлять их в соотстветсвующих пространствах имён, чтобы не было путаницы в именах переменных/констант.
Допустим в математике некий коэффициент g есть и в физике величина g и третий модуль, который использует и математику и физику:
Код:
// math.h

int const g = 15;

// phys.h

float const g = 9.8f

// main.cpp
#include "math.h"
#include "phys.h"

...
int a = g * 15; // какое именно g тут будет использоваться?
В стандарте языка конечно это возможно оговорено, но не все компиляторы соответствуют стандарту, да и к чему сомнительные ситуации создавать. Да и как указать в main.cpp какую именно g использовать (предусмотрено ли это синтаксисом языка без испоьзования пространств имён?)?
А с пространствами имён ситуация уже лучше будет:
Код:
// math.h
namespace math
{
  int const g = 15;
}

// phys.h
namespace phys
{
  float const g = 9.8f
}

// main.cpp
#include "math.h"
#include "phys.h"

...
int a = math::g * phys::g; // как видите никакой путаницы уже нет
pu4koff вне форума Ответить с цитированием
Старый 21.05.2009, 17:48   #6
Levsha100
Заблокирован
Старожил
 
Регистрация: 20.07.2008
Сообщений: 4,032
По умолчанию

Сам изучаю С++, ООП-рулит!
Очень удобно объектами представлять реальные объекты, те писать игры
Можно маленький вопросик(для него, думаю, не стоит создавать даже темы):
Код:
#pragma hdrstop
#include <vector>
#include <iostream>
#include <tchar.h>
//---------------------------------------------------------------------------

#pragma argsused
int _tmain(int argc, _TCHAR* argv[])
{
	vector <int> v;

	std::cout<<v.max_Size();
	return 0;
}
Почему мне пишет компилятор(CodeGear Delphi/C++ 2009) что я неправильно объявил массив?
Levsha100 вне форума Ответить с цитированием
Старый 21.05.2009, 17:51   #7
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,088
По умолчанию

1. вектор, а не массив
2. std::vector< int > v;
pu4koff вне форума Ответить с цитированием
Старый 21.05.2009, 18:00   #8
Qousio
Пользователь
 
Аватар для Qousio
 
Регистрация: 02.05.2009
Сообщений: 27
По умолчанию

Большое спасибо за разьяснения pu4koff, буду тренироватся!
Чем более читаете, не размышляя, тем более, уверяетесь, что много знаете, а чем более размышляете, читая, тем яснее видите, что знаете еще очень мало.
Qousio вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
вопрос по функции WaitForSingleObject shurik_7866 Общие вопросы Delphi 2 08.12.2008 10:53
Создание функции вопрос от новичка C CKent Общие вопросы C/C++ 2 07.12.2008 17:31
Вопрос наверное про функции, а так точно даже не знаю про что. (Вопрос начинющего #6) Albert2008 Общие вопросы Delphi 4 21.08.2008 15:33
Вопрос про правильное написание функции AndreichSB Microsoft Office Excel 6 25.12.2006 19:27