Why I Chose C++
来源:互联网 发布:网络推广多少钱一年 编辑:程序博客网 时间:2024/05/21 21:37
A good way to get into an argument with a computer programmer is to attempt to explain why the language they are using is not as good as the one you are using. Most of the programmers I know are positively religious over their Operating System (see my other article), their development language and finally their text editor.
As you might have inferred by the title, I feel that C++ is the superior computer programming language. I will begin by qualifying that statement somewhat. I learned to program using Pascal and I still feel that it is a good language for learning computer programming. Pascal is type safe, has a very limited number of keywords and encourages good programming principles. The BASIC language in the form of Visual Basic on the other hand is an ideal language for quickly putting together a project, and for taking advantage of data base access and other advanced programming tools such as Microsoft's Component Object Model (COM).
Why is it then that modern operating systems and very large applications are written in C++? Visual Basic and Pascal (in the form of Delphi) barely resemble the ANSI definition of these languages. Each of these languages are proprietary and lock you in to a particular vendor. This does not particularly bother me, since I program exclusively for the Windows environment and use Microsoft's Visual C++ as my development environment. There are other features of C++ that are attractive when doing medium to large scale development:
- Operator overloading (also in Delphi)
- Exceptions (also in Delphi and Java)
- Templates
These are the primary features of C++ that set it apart from its peers. I am not going to mention Object Oriented Programming (OOP) here because Java, VB and Delphi support OOP in some form or fashion. I would place OOP above the other three bullets if I were including it in this discussion.
Operator OverloadingI am sure that many of my C++ peers would disagree with me about the relative importance of the three features that I have selected. Operator overloading is essential to making a library of code "fool proof". First, let's look at a typical example of operator overloading:
The CVeryLong class keeps two private long variables to represent a single 64 bit integer. In this class, we are overloading the less than (<), greater than (>) and equivalence (==) operators to allow comparison of our new 64 bit integer class. This class is obviously not complete since I have not overloaded other key operators such as the arithmetic operators. Here is some sample code using our new class:
Running the program containing the above code, generates the following output:
At this point, we have told the compiler what to do when it sees the >, < or == operators used with our class. We could have just as easily defined GreaterThan, LessThan and EqualTo member functions to do the same thing - and in other languages, this is exactly what you would have to do:
So we have made the notation more concise and consistent with the intrinsic data types, but when we began this discussion, I stated that operator overloading would make the code "fool proof". Notice that in the middle of the sample usage code:
we did not overload the assignment operator, so C++ behaves like most languages when presented with this statement, and simply copies the member variables from one object to the other. What if our class were going to support n-level precision so that at compile time, we do not know how many longs to allocate? We would have to dynamically allocate the variables in the constructor and free them in the destructor. Our member variables might look like this:
The default assignment operator will copy the member variables just as it did before, only now you have two pointers pointing to the same block of allocated memory. When the destructor for the first object runs, it will free the memory block with no problems, but when the second object's destructor runs, it tries to free the same block of memory - bug and crash. Even though you can write a Copy function to do the right thing, you cannot keep some unsuspecting programmer from coding the assignment that "works most of the time". Visual Basic is still "fool proof" at this point because it does not allow dynamic memory allocation, but Pascal (not Delphi) will let you crash and burn at this point.
In C++, the assignment operator would be written as follows:
The conclusion here is that a language should either cripple itself as is the case with Java or VB (no dynamic memory allocation), or provide the programmer with a way of guaranteeing that users of your code cannot use it improperly.
ExceptionsExceptions provide another capability that is hard to duplicate if not supported by the language. Windows NT provides a sophisticated capability called Structured Exception Handling (SEH) where the OS is providing the same type of functionality that is provided by C++. It may be possible to take advantage of SEH in other languages. C++ provides a portable mechanism that will work in all operating systems.
Exception handling is exactly what the name implies - the ability to handle exceptional cases without having to tax the normal case. Look at this example of exception processing:
The output from this code looks like this:
The inner loop is free to run without having to do a test for zero on every iteration - the divide by zero is handled as an exceptional case instead of having to treat is as the "rule". Here is how this condition could be handled without exceptions:
My work involves signal processing in real-time, where every millisecond counts. In the above example, the software could process 2 million integer divides without having to explicitly check for 2 million divide errors, by treating the divide by zero as an "exceptional case".
TemplatesWhile templates may not be able to make your code "fool proof" as can overloaded operators, or faster and more robust by handling exceptions, they are my favorite C++ feature. Templates can save the programmer from having to write a lot of code and they benefit the final product by making it smaller.
Templates are type safe macros that are built on demand, that is whatever part of the template is not used is not included in the code. There are class templates and function templates.
Function TemplatesWith function templates, you can specify a set of functions that are based on the same code, but act on different types or classes. Here is an example of a function template that returns the maximum of two values:
This is a data type independent way of comparing two floats, two ints, two shorts, two chars, etc., without having to write the MaxFloat, MaxInt, MaxShort, MaxChar, etc. Furthermore, if I only use the float in my current application, no code is generated for anything else. If I invoke Max with a float and a char, the compiler will complain. Here is an example use:
The output generated is as follows:
Notice that we are not limited to intrinsic types because of operator overloading. Since our CVeryLong class overloads the greater than (>) operator, it can be used with the Max template as well. Template libraries like the Standard Template Library (STL) and the Active Template Library (ATL) are famous for generating tiny code and being highly re-useable.
If you use another language, imagine what is involved to provide something as simple as the Max template, while making it applicable to any class that you define and also to any class that the users of your library define!
Class TemplatesYou can use class templates to create a family of classes that operate on a type. Look at this example of a balanced binary tree class:
I have specifically used a complex example here, to drive home the point that templates can save you a lot of programming. If you have ever coded a balanced binary tree, you know that it is difficult, and depending on the programming language, messy code to write. I have personally had the pleasure of coding such a library three times in three different languages: C, Pascal and C++. In C and Pascal, I was able to use untyped pointers to allow the tree to hold any data type, but in both of these cases, I limited the key to be a string.
The C++ implementation in the above example can contain any data type, can use any data type for the key, and the implementation is completely type safe!
Let's examine the template's declaration:
The four arguments in the declaration give the data type of the key, how the key is passed into arguments, the data type of the data the tree will contain and how the data is passed into arguments. Here are some examples of how the CTree could be instantiated:
The first case is a tree of CVeryLongs using a CString as the key. The key is passed into arguments as a const char* and the data is passed into arguments using a reference to CVeryLong.
The second case is similar to the first except that the data is a float type.
The third case is a tree of strings that use a long for the key.
In the fourth case, a tree of linked lists of integers (another class template) is using CVeryLong types for the key.
We could use the treeVeryLong template to keep track of programmer salaries:
Actually there is an error in this code - do you see it? We specified in our template declaration that the ARG_DATA parameter was to be a reference to a CVeryLong (ARG_DATA CveryLong&). Since we are passing in a constant here, the compiler will complain. We can correct this error by changing the template declaration to allow data arguments to be passed in by value, or modify the code as follows:
Class templates provide a powerful code reuse mechanism that can save a tremendous amount of programming. In addition to saving development time, use of templates will generally result in much smaller projects. Microsoft ships two libraries with Visual C++: Microsoft Foundation Classes (MFC) and the Active Template Library (ATL). ATL was developed in response to the advent of the Internet, more specifically to the large number of people with slow access (read 28.8k) to the Internet. MFC projects were too large to be practical for creating web page objects that had to be downloaded to the client's computer. ATL was the solution to this problem -- projects based on ATL are very small and quick to download.
ConclusionI readily admit to being a C++ bigot, but it is bigotry born of experience with several languages, operating systems and Windowing systems. Programming code in C++ is a pleasure and I would not look forward to having to return to the old days without operator overloading, exceptions and templates.
License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
William T. Block
Member Bill's recent projects include graphical displays and printing of real-time data for the Oil Industry.
"I started programming Windows' applications right after the release of Windows 1.0 and I am now actively working with Microsoft .NET"
He currently works for Baker Hughes in the Houston, Texas area.
Occupation: Web Developer Location: United States
- Why I Chose C++
- Why I Chose C++
- Why Netflix chose NGINX
- Why We Chose Cpp Over Java
- Why why why why why am i a developer?
- Angular vs React – so which do I chose?
- Why Google chose the Apache Software License over GPLv2 for Android
- Why Google chose the Apache Software License over GPLv2 for Android
- JSTL标签c:if和c:chose--个人笔记
- Why I Like Windows
- Why I Write
- Why am I here?
- Why I'm Here
- Why I Hate Frameworks
- Why I hate frameworks
- why I love wh
- Why I am Here
- why I am here?
- Synchronization in Multithreaded Applications with MFC
- A serialization primer - Part 1
- A serialization primer - Part 2
- Think before you code, Virtual Functions in C++
- MFC under the hood
- Why I Chose C++
- VC中使用ADO操作数据库的方法
- C++中几个比较不常用的关键字
- Boost库的编译
- 一本看到技巧又能保持阳光心态励志书(来自苏鹏的推荐)
- C++中常用的几个小技巧
- 字符串处理技巧
- iostream使用技巧
- STL算法