Работа, ЯП и ООП
Всем привет! Хотел бы поговорить насчёт ЯП, ООП и работы.
Короче недавно прочитал в интернете что язык Си++ плохой, но перепутал с Си, и начал воспоминать про Си. Вчера был жаркий спор насчёт Си++. Во-первых помимо ANSI C++ есть разные Си++ и фреймворки (MFC, .NET, VCL), во-вторых есть разные компиляторы - GCC, Visual C++, BCC, итд. Я пользуюсь гнутым Си++ (т.е. gnu cc) а среда разработки Embarcadero Dev-C++ с GCC. С тем с кем спорил, было сделано предположение оппонентом что Си++ придумали чтобы отказаться от указателей. Я где-то читал, что Си++ программисты часто используют на самом деле Си. Но там путаница с этим, если программист хочет пользоваться Си в Си++, то имхо нужно использовать допустим cstring, cmath, cstdio, итд. Допустим если в Си++ работаешь с string, и чтобы перейти из Си++ к Си есть магическая c_str. GCC не поддерживает format. Когда создаёшь Си++ проект, то Embarcadero Dev-C++ сгенерирует такой код:
#include <windows.h> /* This is where all the input to the window goes to */ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { switch(Message) { case WM_DESTROY: { PostQuitMessage(0); break; } /* All other messages (a lot of them) are processed using default procedures */ default: return DefWindowProc(hwnd, Message, wParam, lParam); } return 0; } /* The 'main' function of Win32 GUI programs: this is where execution starts */ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; /* A properties struct of our window */ HWND hwnd; /* A 'HANDLE', hence the H, or a pointer to our window */ MSG msg; /* A temporary location for all messages */ /* zero out the struct and set the stuff we want to modify */ memset(&wc,0,sizeof(wc)); wc.cbSize = sizeof(WNDCLASSEX); wc.lpfnWndProc = WndProc; /* This is where we will send messages to */ wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* White, COLOR_WINDOW is just a #define for a system color, try Ctrl+Clicking it */ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszClassName = "WindowClass"; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); /* Load a standard icon */ wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); /* use the name "A" to use the project icon */ if(!RegisterClassEx(&wc)) { MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK); return 0; } hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Caption",WS_VISIBLE|WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, /* x */ CW_USEDEFAULT, /* y */ 640, /* width */ 480, /* height */ NULL,NULL,hInstance,NULL); if(hwnd == NULL) { MessageBox(NULL, "Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK); return 0; } /* This is the heart of our program where all input is processed and sent to WndProc. Note that GetMessage blocks code flow until it receives something, so this loop will not produce unreasonably high CPU usage */ while(GetMessage(&msg, NULL, 0, 0) > 0) { /* If no error is received... */ TranslateMessage(&msg); /* Translate key codes to chars if present */ DispatchMessage(&msg); /* Send it to WndProc */ } return msg.wParam; }
Вы тут видите где-нибудь Си++ код? Вот я тоже его не вижу!
Когда обращаешься к Win32 API они все на си.Итак, было у меня уймо время, и было делать нечего, решил я подружить си т.е. Win32 API с си++, вот я сделал базовый класс. см. Control.cpp:
#include "control.h" Control::Control(string text, int x, int y, int width, int height, HWND hParent, int id) { this->text = text; this->clss = "STATIC"; this->x = x; this->y = y; this->width = width; this->height = height; this->hParent = hParent; this->id = id; } Control::Control(string text, int x, int y, int width, int height, HWND hParent) { this->text = text; this->clss = "STATIC"; this->x = x; this->y = y; this->width = width; this->height = height; this->hParent = hParent; this->id = -1; } void Control::show() { if(this->id != -1) this->hThis = CreateWindow(this->clss.c_str(), this->text.c_str(), WS_CHILD | WS_VISIBLE, this->x, this->y, this->width, this->height, this->hParent, (HMENU)this->id, NULL, NULL); else this->hThis = CreateWindow(this->clss.c_str(), this->text.c_str(), WS_CHILD | WS_VISIBLE, this->x, this->y, this->width, this->height, this->hParent, NULL, NULL, NULL); } void Control::show(int style) { if(this->id != -1) this->hThis = CreateWindow(this->clss.c_str(), this->text.c_str(), WS_CHILD | WS_VISIBLE | style, this->x, this->y, this->width, this->height, this->hParent, (HMENU)this->id, NULL, NULL); else this->hThis = CreateWindow(this->clss.c_str(), this->text.c_str(), WS_CHILD | WS_VISIBLE | style, this->x, this->y, this->width, this->height, this->hParent, NULL, NULL, NULL); } void Control::show(int style, int exstyle) { if(this->id != -1) this->hThis = CreateWindowEx(exstyle, this->clss.c_str(), this->text.c_str(), WS_CHILD | WS_VISIBLE | style, this->x, this->y, this->width, this->height, this->hParent, (HMENU)this->id, NULL, NULL); else this->hThis = CreateWindowEx(exstyle, this->clss.c_str(), this->text.c_str(), WS_CHILD | WS_VISIBLE | style, this->x, this->y, this->width, this->height, this->hParent, NULL, NULL, NULL); } void Control::set_text(string text) { this->text = text; SetWindowText(this->hThis, text.c_str()); } string Control::get_text() { string data; data.resize(GetWindowTextLength(this->hThis)+1, '\0'); GetWindowText(this->hThis, LPSTR(data.c_str()), GetWindowTextLength(this->hThis)+1); return data; } void Control::set_x(int x) { this->x = x; refresh(); } int Control::get_x() { return this->x = x; } void Control::set_y(int y) { this->y = y; refresh(); } int Control::get_y() { this->y = y; } void Control::set_width(int width) { this->width = width; refresh(); } void Control::set_height(int height) { this->height = height; refresh(); } int Control::get_width() { return this->width; } int Control::get_height() { return this->height; } void Control::refresh() { MoveWindow(this->hThis, this->x, this->y, this->width, this->height, true); } void Control::set_class(string clss) { this->clss = clss; } bool Control::isClicked(WPARAM p) { if(this->id != -1 && this->id == LOWORD(p)) return true; return false; } HWND Control::get_handle() { return this->hThis; } Control::~Control() { }
Control.h:
#ifndef CONTROL_H #define CONTROL_H #include <windows.h> #include <string> using namespace std; class Control { private: HWND hParent; HWND hThis; string text; string clss; int x; int y; int width; int height; int id; private: void refresh(); public: Control(string text, int x, int y, int width, int height, HWND hParent); Control(string text, int x, int y, int width, int height, HWND hParent, int id); virtual ~Control(); void set_text(string text); string get_text(); void set_x(int x); void set_y(int y); int get_x(); int get_y(); void set_width(int width); void set_height(int height); int get_width(); int get_height(); void show(); void show(int style); void show(int style, int exstyle); bool isClicked(WPARAM p); void set_class(string clss); HWND get_handle(); }; #endif
Вот так я подружил Си++ с ComboBox:
#include "combobox.h" ComboBox::ComboBox(string title, int x, int y, int width, int height, HWND hParent): Control(title, x, y, width, height, hParent) { Control::set_class("COMBOBOX"); } ComboBox::ComboBox(string title, int x, int y, int width, int height, HWND hParent, int id) : Control(title, x, y, width, height, hParent, id) { Control::set_class("COMBOBOX"); } void ComboBox::add_item(string text) { SendMessage(this->get_handle(), CB_ADDSTRING, 0, (LPARAM)text.c_str()); } long ComboBox::get_count() { return SendMessage(this->get_handle(), CB_GETCOUNT, 0, 0); } long ComboBox::get_selected_index() { return SendMessage(this->get_handle(), CB_GETCURSEL, 0, 0); } string ComboBox::get_item(long item_index) { char buf[4096]; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SendMessage(this->get_handle(), CB_GETLBTEXT, (WPARAM)item_index, (LPARAM)buf); string data(buf); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! return data; } void ComboBox::delete_item(long item_index) { SendMessage(this->get_handle(), CB_DELETESTRING, (WPARAM)item_index, 0); } void ComboBox::clear() { SendMessage(this->get_handle(), CB_RESETCONTENT, 0, 0); }
Переход из Си++ в Си, и обратно, я считаю каким-то маразмом.
Мне дали чётко понять что моя нисша не C#, Си++, итд, а PHP! Короче лет 10 назад когда меня арбайтсамт дёргал чтобы я писал бевербунги, я писал бевербунги на программиста PHP, там требовались знания фреймворков, хотя я их не знал. Допустим пишу бевербунги в г. Мюнхен, там у одной фирмы стоит что нужно знать Symfony, в другой фирме нужно знать CakePHP, в третьей фирме Zend Framework, в четвёртой фирме Laravel. Фреймворки похожи, самая сложная наверное Symfony, т.к. проект создаётся через командную строку. Я освоил Kohana Framework и NuSOAP, кстати благодаря NuSOAP я смог подружить ASP.NET с PHP. После того как я поиграл с Kohana, я создал свой PHP фреймворк. Короче я работал с Reflection чтобы подружить с моим ORM, пишишь вот так:
<?php class Messages extends ORM { /** * @type:integer * @autoincrement:true * @unsigned:true * @primarykey:true */ public $messageid; /** * @type:varchar(255) * @is_null:false * @annotation:"Author:" */ public $author; /** * @type:text * @is_null:false * @annotation:"Message:" */ public $message; /** * @type:DATETIME * @is_null:false * @annotation:"Date:" */ public $date; /** * @type:varchar(255) * @is_null:false * @annotation:"E-mail:" */ public $email; }
А благодаря моему ORM т.е. если напишишь вот так
$obj_orm_messages = ORM::factory('messages'); //$arr_messages = $obj_orm_messages->select('', array('limit' => $int_limit, 'offset' => $int_offset, 'orderby' => array('date ASC')));
получал вот так:
CREATE TABLE Messages(messageid INTEGER NOT NULL AUTO_INCREMENT, author VARCHAR(255) NOT NULL, message TEXT NOT NULL, date DATETIME NOT NULL, PRIMARY KEY(messageid))
Когда программируешь на Symfony, Zend Framework, Laravel, итд. Есть определённые правила и табу. Допустим во вьюшках писать вот такое это табу:
<link rel="stylesheet" type="text/css" src=""> <script src=""></script> <form method="post" action=""> <input type="text"> <input type="submit" value="send"> </form>
Вместо тегов используешь так называемые хелперы, это статичные методы определённых классов, т.е. фактически программируешь на структуироном языке. Потом я был ошарашен, но эти фреймворки загружаются в память где-то на 100 мбайт/пользователь.
Так-же в своём фреймворке я сделал так:
<?php class DB { private $str_sql; private $is_order_by_first; private $is_non_query; private $is_group_by_first; // general public function __construct() { } private function set_sql($str_sql) { $this->str_sql = $str_sql; } private function get_sql() { return $this->str_sql; } public function exec() { $str_sql = $this->get_sql(); $arr_rows = array(); $arr_config = Config::get('config'); $obj_db = new mysqli($arr_config['database_connection']['server'], $arr_config['database_connection']['username'], $arr_config['database_connection']['password'], $arr_config['database_connection']['database']); $obj_result = $obj_db->query($str_sql); if($this->is_non_query == false) { if($obj_db->connect_errno == 0) { $int_index = 0; while($arr_row = $obj_result->fetch_assoc()) { $arr_rows[$int_index] = $arr_row; $int_index ++ ; } } $obj_db->close(); return $arr_rows; } elseif($this->is_non_query == true) { $obj_db->close(); return @$obj_db->insert_id; } } // SELECT Begin public function select($str_select = '*') { $this->is_order_by_first = true; $this->is_group_by_first = true; $this->is_non_query = false; $this->set_sql('SELECT ' . $str_select . ' ' ); return $this; } public function from($str_from) { $str_sql = $this->get_sql(); $this->set_sql($str_sql . ' FROM ' . $str_from); return $this; } private function where_abstract($str_where, $str_character, $str_type, $str_value) { $str_sql = ''; $str_value2 = ''; if($str_type == 'string') $str_value2 = ' ' . $str_character . '\'' . $str_value . '\''; elseif($str_type == 'date') $str_value2 = ' ' . $str_character . '\'' . $str_value . '\''; elseif($str_type == 'integer') $str_value2 = ' ' . $str_character . $str_value; $str_sql .= $str_where . ' ' . $str_value2; return $str_sql; } public function where($str_where, $str_character, $str_type, $str_value) { $str_sql = $this->get_sql(); $str_sql2 = $this->where_abstract($str_where, $str_character, $str_type, $str_value); $this->set_sql($str_sql . ' WHERE ' . $str_sql2); return $this; } public function or_where($str_where, $str_character, $str_type, $str_value) { $str_sql = $this->get_sql(); $str_sql2 = $this->where_abstract($str_where, $str_character, $str_type, $str_value); $this->set_sql($str_sql . ' OR ' . $str_sql2); return $this; } public function where_open() { $str_sql = $this->get_sql(); $this->set_sql($str_sql . ' ( '); return $this; } public function where_close() { $str_sql = $this->get_sql(); $this->set_sql($str_sql . ' ) '); return $this; } public function and_where($str_where, $str_character, $str_type, $str_value) { $str_sql = $this->get_sql(); $str_sql2 = $this->where_abstract($str_where, $str_character, $str_type, $str_value); $this->set_sql($str_sql . ' AND ' . $str_sql2); return $this; } public function join($str_type, $str_table) { $str_sql = $this->get_sql(); $str_sql .= ' ' . $str_type . ' ' ; $str_sql .= $str_table; $this->set_sql($str_sql); return $this; } public function on($str_key1, $str_key2, $str_operator = '=') { $str_sql = $this->get_sql(); $str_sql .= ' ' . $str_key1 . ' ' . $str_operator . ' ' . $str_key2; $this->set_sql($str_sql); return $this; } public function order_by($str_field, $str_key) { $str_sql = $this->get_sql(); if($this->is_order_by_first == false) { $this->set_sql($str_sql . ', ' . $str_field . ' ' . $str_key); return $this; } if($this->is_order_by_first == true) { $this->is_order_by_first = false; $this->set_sql($str_sql . ' ORDER BY ' . $str_field . ' ' . $str_key); return $this; } } public function group_by($str_field) { $str_sql = $this->get_sql(); if($this->is_group_by_first == false) { $this->set_sql($str_sql . ', ' . $str_field); } if($this->is_group_by_first == true) { $this->is_group_by_first = false; $this->set_sql($str_sql . ' GROUP BY ' . $str_field); } return $this; } public function limit($int_offset, $int_count = '') { $str_sql = $this->get_sql(); $str_sql2 = ' LIMIT ' . $int_offset; if($int_count != '') $str_sql2 .= ',' . $int_count; $this->set_sql($str_sql . $str_sql2); return $this; } // SELECT End // INSERT Begin public function insert($str_table, $arr_columns) { $str_sql = 'INSERT INTO ' . $str_table . '('; $this->is_non_query = true; $int_index = 0; foreach($arr_columns as $str_column) { $str_sql .= $str_column; if($int_index < count($arr_columns) - 1) $str_sql .= ','; $int_index ++ ; } $str_sql .= ') '; $this->set_sql($str_sql); return $this; } public function values($arr_values) { $str_sql = $this->get_sql(); $str_sql .= ' VALUES('; $int_index = 0; foreach($arr_values as $str_key => $arr_value) { if($arr_value['type'] == 'string') $str_sql .= '\'' . $arr_value['value'] . '\''; elseif($arr_value['type'] == 'date') $str_sql .= '\'' . $arr_value['value'] . '\''; elseif($arr_value['type'] == 'integer') $str_sql .= $arr_value['value']; if($int_index < count($arr_values) - 1) $str_sql .= ','; $int_index ++ ; } $str_sql .= ')'; $this->set_sql($str_sql); return $this; } // INSERT End // UPDATE Begin public function update($str_table) { $str_sql = 'UPDATE ' . $str_table; $this->set_sql($str_sql); return $this; } public function set($arr_fields) { $str_sql = $this->get_sql(); $str_sql .= ' SET '; $int_index = 0; foreach($arr_fields as $arr_field) { if($arr_field['type'] == 'string') $str_sql .= $arr_field['name'] . '=\'' . $arr_field['value'] . '\''; elseif($arr_field['type'] == 'date') $str_sql .= $arr_field['name'] . '=\'' . $arr_field['value'] . '\''; elseif($arr_field['type'] == 'integer') $str_sql .= $arr_field['name'] . '=' . $arr_field['value']; if($int_index < count($arr_fields) - 1) $str_sql .= ','; $int_index ++ ; } $this->set_sql($str_sql); return $this; } // UPDATE End // DELETE Begin public function delete() { $this->is_non_query = true; $str_sql = 'DELETE '; $this->set_sql($str_sql); return $this; } // DELETE End }
Поэтому у меня неприязнь к ООП.