📜 ⬆️ ⬇️

Comparative analysis of C # and C ++ languages

Let's take a closer look at these two languages. What is important for a diligent programmer? So that its code is readable, so that at any time, after any time, you can change this code.

C ++


What does C ++ teach us, what does it tell us, what paradigms does it erect?

1. What can be called types, methods and variables in small letters
')
std::list<std::string> L; L.push_back(50); L.push_front(-50); 

You ask what is wrong with naming the elements in small letters?

And the fact that, firstly, C ++ does not distinguish between the type context and the context of a variable and a function! And you can’t take and declare a field, say, size or point point! Therefore, it makes sense to call functions and variables in small letters, but only if the type is named in C # style, and naming the type in small letters spoils the whole point of such an action! And the point is that it is impossible to intersect the type name and its members!

Well, and secondly, naming as C #, looks more solid, more beautiful.

Although, of course, you can name it exactly as it is now proposed, but not the fact that others will follow this rule.

2. What can be reduced in such a way that it will be incomprehensible to those who use your code, but “print quickly”. Or abbreviate, but still understandable.

Here are some of the methods from the standard library:

  std::string s; s.rfind(); s.c_str(); std::fstream fs; fs.copyfmt(); fs.rdbuf(); 

Do you understand anything? What is “rfind” and why not “find”, what is this r for? What is "c_str"? It is necessary to look at the documentation in order to understand that this transformation of a string into a “string as in C” is an array-pointer to characters ...

3. That you can use macros as a universal means of solving problems. In this case, it is intentionally forgotten, or is silent, that these macros can be easily replaced, and that they are global, not included in any namespace.

For example:

  #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 

Please also note that if the parameters of a parameterized macro are not enclosed in parentheses, then all calculations with this macro will easily deteriorate! But the fact is that the parameters of the macro being opened are perceived as text (!), And if you do not put brackets, we will get something like this:

  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; 

Agree, this is not what we expected! And only those who have learned this trick of macros with parameters on their own bitter experience, long ordeal and exclamations: “God, what I did not do that!” (Or those who read the documentation for the language) write these macros correctly (and you need to be very careful!) .

4. What are you yourselves! - should do many things that in C ++ were too lazy to do.


And there are many more such things. Of course, you can find ready-made solutions. But it is not known what quality they will be, whether you will find them at all; besides, they will need to adjust to your style.

5. That you can mess around with pointers and even with constant pointers, you just need to correctly convert types. Take a look:

  void Func(const int* x) { ((int*)x)[0] = 5; } int main() { int m = 500; Func(&m); std::cout << m <<'\n'; return 0; } 

And what will appear with us? five! The constant parameter has changed its value! So any constant pointers can be changed, even string or numeric (although their change causes a memory handling error). Or here:

  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 << tM <<" "<< tN << "\n"; return 0; } 

Here the static constant of structural type changes! That is, the one in whose immutability we are 100% sure! “But no!” Says C ++. And it is the modified value of the constant that is output.

6. That it is possible to dump the contents of listings into the general context! Moreover, without the inclusion of the standard C ++ 11, we can not do otherwise.

It's horrible! Take a look at this:

  enum Month { JANUARY,FEBRUARY, MARCH,APRIL,MAY, JUNE,JULY,AUGUST, SEPTEMBER,NOVEMBER, DECEMBER }; ... Month m = JANUARY; ... switch(x) { case JANUARY: case FEBRUARY: } 

And if the elements intersect, are they present in one and in another enumeration (for example, such completely recurring “NORMAL”, “DEFAULT”)? What then? .. C ++ allows the call to enums in this way! The lazy loose C ++ programmers will say: “And what is also spelled faster, it is also possible!”, They didn’t know that this is licentiousness, as was unheard of for those who go to modern Russian comedies (“And what’s funny, like in life!”) !

Even if you want to call correctly (suppose you are a decent C ++ programmer using someone’s code), it turns out to be ugly and ugly - you get a combination of a constant style (element) and a C # style (enum name), and you have to write without a name listing, so it was at least beautiful.

Although, of course, you can be decent and call the enumeration elements correctly (as enums themselves (here, in general, it is unlikely that the type name and its element will intersect, so the style can be the same, which is preferable, because it's more beautiful)) and not throw out elements in context, even forbidding it by adding the word “class” after ”enum" (standard C ++ 11). But it is not a fact here that the others will be as decent and follow the rules!

Correctly do so:

  enum class Month { January, February, March,April,May, June,July,August, September,October,November, December }; 

7. That such things as are not at all a mistake:


But at least there are warnings about this, but sometimes they forget to read them, and they are formed only after compilation, until we read them, an error can occur, because we usually compile with a further launch.

And, the most terrible thing is that in order to substitute a variable for the reference parameter when calling, no additional words are needed. This is terrible, as it leads to the fact that the call can be perceived as a call without any changes in parameters. Take a look:

  void F(int& x, int& y); . . . F(x,y); void FF(int x, int y); FF(x,y); 

What do we see? We see that IF A REFERENCE SIGN IS REFERRED, THEN THE CHALLENGE WILL NOT CHANGE. We may not know where the reference parameter is, where the parameter value is! Only by the meaning of the function or by activating the hint in the IDE can we determine this!

Let's sum up


With ++ it tells us: I do not have some important things, you have to get it or write them yourself, and there are no clear rules in our "democratic" language, live as you wish!

C ++ teaches us: write ugly, depraved, using macros, double-triple-quadruple underscores, shortening names to obscure, but fast-typing, throwing enumeration elements into the general context, freely referring to pointers, even changing the contents of constants, and indeed to we will not swear at some things interrupting the compilation, but only warn you ... As if to say: no one forbids you to do this, all restrictions are decided!

Meanwhile, such teachings and paradigms only spoil the diligent programmers, moreover, forcing them to create / search for some basic, necessary, solutions, have a bad effect on the outlook and nerves of the programmer and leading to a deterioration in the readability of the code ...

C #


But take a look at C #! What does he tell us, what paradigms does he erect, what does he teach?

1. That words in type names, functions, variables begin with a capital letter and are connected without separators (thanks to large letters, words are visible). This is called the C # style (another name is Pascal style), a representative of the camel style group. That the first word of the name of each closed variable begins with a small one, so as not to be confused with the open - the Java style, the second representative of the camel's style group.

The context of type names is different from the context of the names of functions, variables and constants. You can declare a Size Size or Point Point field, and it will compile and you can even use it correctly (even combine the field name and type name without using 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. With no abbreviations outside the context of the function! Its naming style in std. C # libraries show an example to the rest - how to correctly name the elements of the code, this style is beautiful and inspiring for feats. No abbreviations, camel style with a capital letter, no underscores, you will not find them at all! Each word is complete, or is an abbreviation (which, of course, is allowed), also starting with a large one, and then with small ones.

  XmlDocument document = new XmlDocument(); Rectangle rect = new Rectangle(300,500,1000,500); 

3. The possibilities of macros are cut to the limit. You can only declare and check whether there is such-and-such a macro, and some macros are declared through the compiler settings. Everything!

  #define M ... #if M double M = 53; #endif 

Moreover, the name of the macro and the name of the element (type / function / variable / constant) are parallel, not connected in any way, you can call the same name as a macro and a variable (or another element).

Here are some safe macros.

4. That many, many things are already well done in C #, and the normal, solid style makes them self-documenting and understandable, especially after reading the documentation.

There are plenty of classes and namespaces in the main assemblies that you have not yet learned. And this is just the main assembly, and there are many others!

In the main assemblies made:

And there are many more additional ones, among them there are 2 main ones used in window applications: System.Windows.Forms * (for working with GUI) and System.Drawing * (for working with graphics)

Also, there are some useful built-in things in the language that are not found in C ++:

  class Example { int X{get; set;} int Y{get; set;} object Object{ get{return object;} set{object = value==null ? new object() : value;} } } ... foreach(String arg in args) { Console.WriteLine( arg ); } ... 


5. What you can not just take and indulge pointers. To do this, you need to enable unsafe code in the compilation settings and mark the class as unsafe by adding “unsafe” to the list of its modifiers. And only after that it will be possible to work with them.
Besides, impossible, impossible! - get the address of a constant or read-only variable, which makes it impossible to change it! - and we can sleep peacefully with a sweet dream, knowing that C # will not allow constants and unchangeable variables to offend every sadist, oh, that is, change!

  unsafe class C { int* n; static void Main() { byte* n = (byte*)(5); n = (byte*)(n+3); } } 

6. That the elements of enums remain in the context of enumerations and do not fall out into the global context. And they are written (by convention) in the same style - the C # style - as the name of the enumeration containing them.

  enum DayOfWeek { Monday = 1, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } 

In C #, no function / variable / constant can be outside the class.

7. That many errors that a programmer negligently misses, to identify which algorithms can be identified, C # detects and says that this is an error, interrupting the compilation if this error affects the work, and some remain as a warning if they do not. That is, inadvertent errors.

Among the errors:


Among the warnings are:



In addition, function parameters can have one of two modifiers:
1. ref - link transfer, in the declaration and transfer of a link variable, you must explicitly indicate this word in front.
2. out - the same, but the variable may not yet be declared.

  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); 

And when we call a function, we can see where we are passing the link, and where is the value. This is great, this is a good language rule.

There are other useful limitations:


Let's sum up


C # tells us: program in pleasure, I have everything for this: wonderful language rules, naming rules, as well as various useful libraries.

C # teaches us: use the correct naming style, forget about any underscores, they are unnecessary; Forget free global variables and functions, everything is in classes; Do not consider restrictions to be far-fetched, but consider them to be correct and ordering your thinking, write according to the rules and you will acquire nirvana!

Very useful and necessary for a decent programmer teachings and paradigms that have a great effect on the mood and worldview and lead to order in the head and the code.

Conclusion


If you want to become a supporter of the corrupting democracy C ++, then there you and the road, you have the right to make this choice. But if you are ready to comprehend nirvana in programming, to preserve your nerves, health and sanity, then your choice is C #.

Source: https://habr.com/ru/post/273331/


All Articles