- PVSM.RU - https://www.pvsm.ru -
Давайте взглянем на эти два языка внимательнее. Что важно для прилежного программиста? Чтобы его код был удобочитамым, дабы в любой момент, спустя любое время можно было изменить этот код.
Чему учит нас C++, что он нам говорит, какие парадигмы он воздвигает?
1. Что можно именовать типы, методы и переменные маленькими буквами
std::list<std::string> L;
L.push_back(50);
L.push_front(-50);
Вы спросите, что же плохого в именовании элементов маленькими буквами?
А то, что, во-первых, C++ не различает контекст типа и контекст переменной и функции! И вы не можете никак взять и объявить поле, скажем, size size или point point! Поэтому, имеет смысл именовать функции и переменные маленькими буквами, но только если тип именуется в стиле C#, а именование типа маленькими буквами портит весь смысл такого действия! А смысл заключается в невозможности пересечения имени типа и его членов!
Ну, а во-вторых, именование как C#, выглядит солиднее, красивее.
Хотя, конечно, вы можете именовать именно так как сейчас предложено, но не факт, что другие будут следовать этому правилу.
2. Что можно сокращать так, что будет непонятно тому, кто использует ваш код, но зато «быстро печатается». Или сокращать, но все же понятно.
Вот лишь некоторые методы из стандартной библиотеки:
std::string s; s.rfind(); s.c_str();
std::fstream fs; fs.copyfmt(); fs.rdbuf();
Вы что-нибудь поняли? Что есть «rfind» и почему не «find», что это за r такая? Что такое «c_str»? Нужно посмотреть документацию, чтобы понять, что это превращение строки в «строку как в С» — массив-указатель на символы…
3. Что можно использовать макросы, как универсальное средство решения проблем. При этом намеренно забывается, или умалчивается, что эти макросы можно легко заменить, и что они глобальны, не входят в какое-либо пространство имён.
Вот например:
#define foreach(x,c) for(auto x = c.begin(); x != c.end(); x++)
#define min(x,y) ((x)<(y) ? (x) : (y))
#define true false
#define NULL 1
Обратите также внимание на то, что если параметры параметризованного макроса не обставлять скобками, то все вычисления с этим макросом легко испортятся! А дело в том, что параметры раскрываемого макроса воспринимаются как текст (!), и если не поставить скобки, то мы получим примерно такие варианты:
a = b * min(x,y); //==> a = b*x < y ? x : y;
a = min(5,3*k)*100; //==> a = 5 < 3*k ? 5 : 3*k*100;
Согласитесь, это не то, что мы ожидали! И только познавшие эту хитрость макросов с параметрами на своем горьком опыте, долгих мытарствах и восклицаниях: «боже, что я не так сделал!» (или прочитавшие документацию к языку), пишут такие макросы правильно (и то, нужно быть очень внимательным!).
4. Что вы сами, сами! ‒ должны делать многие вещи, которые в C++ поленились сделать.
И таких вещей много еще. Конечно, можно найти и готовые решения. Но неизвестно, какого они качества будут, найдете ли вы их вообще; к тому же, их нужно будет подстроить под свой стиль.
5. Что можно свободно баловаться с указателями и даже с константными указателями, надо лишь правильно преобразовать типы. Взгляните:
void Func(const int* x) {
((int*)x)[0] = 5;
}
int main() {
int m = 500;
Func(&m);
std::cout << m <<'n';
return 0;
}
И что же выведется у нас? 5! Константный параметр изменил свое значение! Так можно любые константные указатели менять, даже строковые или числовые (правда их изменение влечет ошибку обращения с памятью). Или вот:
struct T {
int M,N;
T(int m, int n) {
M = m; N = n;
}
};
int main() {
static const T t = T{5,3};
((T*)(&t))[0] = T(-1,-5);
std::cout << t.M <<" "<< t.N << "n";
return 0;
}
Здесь изменяется статическая константа структурного типа! То есть, та, в чьей неизменяемости мы уверены на все 100%! «А вот нет!» — говорит на C++. И выводится именно изменённое значение константы.
6. Что можно вываливать содержимое перечислений в общий контекст! При чем, без включения стандарта C++11, мы не сможем сделать иначе.
Это ужасно! Взгляните на это:
enum Month {
JANUARY,FEBRUARY,
MARCH,APRIL,MAY,
JUNE,JULY,AUGUST,
SEPTEMBER,NOVEMBER, DECEMBER
};
...
Month m = JANUARY;
...
switch(x) {
case JANUARY:
case FEBRUARY:
}
А если элементы пересекаются — присутствуют и в одном, и в другом перечислении (например, такие вполне могущие повторяться «NORMAL», «DEFAULT»)? Что тогда?.. C++ попускает вызов перечислений именно таким образом! Ленивые распущенные программисты C++ скажут: «А что, также быстрее пишется, также можно!», им невдомёк, что это распущенность, как невдомёк тем, кто ходит на современные российские комедии («А что, это прикольно, как в жызни!»)!
Даже если вы хотите правильно вызвать (допустим, вы порядочный программист C++, использующий чей-то код), то получается и вовсе некрасиво, уродливо ‒ получается сочетание константного стиля (элемент) и стиля C# (имя перечисления), и вы вынуждены писать без имени перечисления, дабы было хотя бы красиво.
Хотя, конечно, вы можете быть порядочным и именовать элементы перечисления правильно (как сами перечисления (здесь, вообще, врятли будет пересечение имени типа и его элемента, потому может быть одинаковый стиль, что предпочтительнее, т.к. красивее)) и не вываливать элементы в контекст, даже запрещая это добавлением слова «class» после ”enum" (стандарт C++11). Но не факт и здесь, что остальные будут такими же порядочными и соблюдать правила!
Правильно делать так:
enum class Month {
January, February,
March,April,May,
June,July,August,
September,October,November, December
};
7. Что вовсе не являются ошибкой такие вещи как:
Зато об этом есть хотя бы предупреждения, но порою забывают прочесть, и они образуются только после компиляции, пока мы их прочтем, может произойти ошибка, ведь мы обычно компилируем с дальнейшим запуском.
И, самая страшная вещь ‒ чтобы подставить на место параметра-ссылки переменную при вызове, не надо никаких дополнительных слов. Это ужасно, так как ведет к тому, что вызов может быть воспринят как вызов без каких-либо изменений параметров. Взгляните:
void F(int& x, int& y);
. . .
F(x,y);
void FF(int x, int y);
FF(x,y);
Что мы видим? Мы видим, что ЕСЛИ УБРАТЬ ЗНАК ССЫЛКА, ТО ВЫЗОВ НЕ ИЗМЕНИТСЯ. Мы можем не знать, где ссылочный параметр, где параметр-значение! Лишь по смыслу функции или при активации подсказки в IDE мы можем это определить!
С++ нам говорит: у меня нет некоторых важных вещей, ты должен достать или написать их сам, а еще в нашем «демократическом» языке нет четких правил, живите как хотите!
С++ нас учит: пишите безобразно, развратно, используя макросы, двойные-тройные-четверные подчеркивания, сокращая имена до малопонятных, но быстропечатаемых, вываливая элементы перечислений в общий контекст, свободно обращаясь с указателями, даже изменяя содержимое констант, да и вообще на некоторые вещи мы не будем ругаться прерывая компиляцию, а лишь предупредим вас… Как бы говоря: вам никто не запрещает этого, все ограничения надуманы!
Меж тем, такие учения и парадигмы лишь портят прилежных программистов, к тому же, заставляя их создавать/искать некоторые базовые, необходимые, решения, плохо сказывась на мировоззрении и нервах программиста и ведущие к ухудшении удобочитаемости кода…
Но взглянем на C#! Что же он нам говорит, какие парадигмы воздвигает, чему же учит?
1. Что слова в именах типов, функций, переменных начинаются с большой буквы и соединяются без разделителей (благодаря большим буквам слова видны). Это называется стилем C# (другое название ‒ стиль Pascal), представитель верблюжей группы стилей. Что первое слово имени каждой закрытой переменной начинается с маленькой, дабы не путать с открытыми ‒ стиль Java, второй представитель верблюжей группы стилей.
Контекст имен типов отличается от контекста имен функций, переменных и констант. Вы можете объявить поле Size Size или Point Point, и это скомпилируется и можно будет даже правильно использовать (даже сочетать имя поля и имя типа без использования this!)!
struct Rect {
Point Point;
Size Size;
// Функции...
Rect(int x,int y,int w,int h) {
Size = new Size(w,h);
Point = new Point(x,y);
}
...
}
Rect r = new Rect(new Point(5,5), new Size(300,200));
2. Что никаких сокращений вне контекста функции! Своим стилем именования в стд. библиотеках C# показывает пример остальным ‒ как правильно именовать элементы кода, стиль этот красив и вдохновляет на подвиги. Никаких сокращений, верблюжий стиль с заглавной буквы, никаких подчеркиваний, вы их вообще не найдете! Каждое слово полно, либо является аббревиатурой (что, естественно допускается), также начинающейся с большой, а далее ‒ маленькими.
XmlDocument document = new XmlDocument();
Rectangle rect = new Rectangle(300,500,1000,500);
3. Возможности макросов урезаны до предела. Можно лишь объявлять и проверять, есть ли такой-то — такой-то макрос, а некоторые макросы объявляются через настройки компилятора. Всё!
#define M
...
#if M
double M = 53;
#endif
Причём имя макроса и имя элемента (тип/функция/переменная/константа) параллельны, никак не связаны, можно одинаково называть и макрос и переменную (или другой элемент).
Вот какими безопасными могут быть макросы.
4. Что многие, многие вещи уже качественно сделаны в C#, а нормальный, солидный стиль делает их еще и самодокументирующимися, понятными, особенно после прочтения документации.
Полно еще классов и пространств имен в основных сборках, которые еще не изучены вами. И это еще только основные сборки, а есть еще множество других!
В основных сборках сделаны:
А есть еще много дополнительных, среди них можно выделить 2 основные, используемые в оконных приложениях: System.Windows.Forms* (по работе с GUI) и System.Drawing* (по работе с графикой)
5. Что нельзя просто так взять и побаловаться указателями. Вам нужно для этого разрешить небезопасный код в настройках компиляции и обозначить класс как небезопасный, добавив «unsafe» в список его модификаторов. И только после этого можно будет с ними работать.
Кроме того, невозможно, невозможно! ‒ получить адрес константы или переменной только для чтения, что делает невозможным её изменение! ‒ и мы можем спокойно спать сладким сном, зная, что C# не даст константы и неизменяемые переменные в обиду всяким садистам, ой, то есть, изменять!
unsafe class C {
int* n;
static void Main() {
byte* n = (byte*)(5);
n = (byte*)(n+3);
}
}
6. Что элементы перечислений остаются в контексте перечислений и не вываливаются в глобальный контекст. И они пишутся (по соглашению) в таком же стиле ‒ стиле C# ‒ как и имя содержащего их перечисления.
enum DayOfWeek {
Monday = 1, Tuesday, Wednesday,
Thursday, Friday, Saturday, Sunday
}
В C# вообще ни одна функция, переменная или константа не могут находиться вне класса.
7. Что многие ошибки, которые программист по невнимательности пропускает, на выявление которых можно определить алгоритм, C# обнаруживает и говорит, что это ошибка, прерывая компиляцию, если эта ошибка влияет на работу, а некоторые остаются как предупреждение, если не влияют. То есть, ошибки по невнимательности.
Среди ошибок:
Среди предупреждений:
Кроме того, параметры могут иметь один из двух модификаторов:
1. ref ‒ передача ссылки, в объявлении и передаче ссылке переменную нужно явно указать это слово впереди.
2. out ‒ то же самое, но переменная еще и может быть не объявлена
void F(ref int x,ref int y){ ... }
void O(out float j,out float k){ ... }
...
int x = 0, y = 0;
F(ref x,ref y);
int j,k;
O(out j,out k);
И мы при вызове функции можем видеть, где мы передаем ссылку, а где ‒ значение. Это здорово, это хорошее правило языка.
Есть и другие полезные ограничения:
C# нам говорит: программируйте в удовольствие, у меня для этого всё есть: замечательные правила языка, правила именования, а также разные полезные библиотеки.
C# нас учит: используйте правильный стиль именования, забудьте про всякие подчеркивания, они излишни; забудьте про свободно гуляющие глобальные переменные и функции, у нас все находится в классах; не считайте ограничения надуманными, а считайте их правильными и упорядывающими ваше
Весьма полезные и нужные порядочному программисту учения и парадигмы, отлично сказывающиеся на настроении и мировоззрении и ведущие к порядку в голове и коде.
Если вы хотите стать приверженцем развращающей демократии C++, то туда вам и дорога, вы вправе сделать этот выбор. Но если вы готовы постичь нирвану в программировании, сохранить свои нервы, здоровье и здравомыслие, то ваш выбор ‒ C#.
Автор: GLAUBEROV
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/c-2/106472
Ссылки в тексте:
[1] мышление: http://www.braintools.ru
[2] Источник: http://habrahabr.ru/post/273331/
Нажмите здесь для печати.