Return to Discovering Modern C++, C++ DevOps, C++ books, C++ courses, C++ topics, C++
Chapter 2
Classes
“Computer science is no more about computers than astronomy is about [wp>telescopes.” — Edsger W. Dijkstra
“And computer science is more than drilling on programming language details. That said, this chapter will not only provide information on declaring C plus plus classes but also give you an idea of how we can make the best use of them, how they best serve our needs. Or even better: how a C plus plus class can be used conveniently and efficiently in a broad spectrum of situations. We see classes not only as a way of bundling data but primarily as instruments to establish new C plus plus abstractions in our C plus plus software.”
2.1 Program for Universal Meaning, Not Technical Details Writing leading-edge engineering or scientific software with a mere focus on performance details is very painful and likely to fail. The most important tasks in scientific and engineering programming are:
Identifying the mathematical abstractions that are important in the domain, and
Representing these abstractions comprehensively and efficiently in software.
Or for short:
Advice
Use the right abstractions! If they do not exist, implement them.
Focusing on finding the right representation for domain-specific software is so important that this approach evolved into a programming paradigm: Domain-Driven Design (DDD). The core idea is that software developers regularly talk with the domain experts about how software components should be named and behave so that the resulting software is as intuitive as possible (not only for the programmer but even more so for the user). The paradigm is not thoroughly discussed in this book. We rather refer to other literature like [72].
Common abstractions that appear in almost every scientific application are vector spaces and linear operators. The latter project from one vector space into another. When incorporating them into software, we should first decide how to represent these abstractions best.
Let v be an element of a vector space and L a linear operator. Then C++ allows us to express the application of L on v as:
L(v) Or as:
L * v Which one is better suited in general is not so easy to say. However, it is obvious that both notations are much better than
Click here to view code image
apply_symm_blk2x2_rowmajor_dnsvec_multhr_athlon(L.data_addr ,
L.nrows, L.ncols, L.ldim, L.blksch, v.data_addr, v.size);which exposes lots of technical details and distracts from the principal tasks. Developing software in that style is far from being fun. It wastes so much energy of the programmer. Even getting the function calls right is much more work than with a simple and clear interface. Slight modifications of the program—like using another data structure for some object—can cause a cascade of modifications that must be meticulously applied. Remember that the person who implements the linear projection wants to do science, actually.
The Purpose of Scientific Software
Scientists do research. Engineers create new technology.
Excellent scientific and engineering software is expressed only in mathematical and domain-specific operations without any technical detail exposed.
At this abstraction level, scientists can focus on models and algorithms, thus being much more productive and advancing scientific discovery.
The cardinal error of scientific software providing low-level interfaces like that of the last example (and sadly, we have seen even worse than that) is to commit to too many technical details in the user interface. The reason lies partly in the usage of simpler programming languages such as C and Fortran 77 or in the effort to interoperate with software written in one of those languages. If you ever are forced to write software that interoperates with C or Fortran, write your software first with a concise and intuitive interface in C++ for yourself and other C++ programmers and encapsulate the interface to the C and Fortran libraries so that it is not exposed to the developers.
It is admittedly easier to call a C or Fortran function from a C++ application than the other way around. Nonetheless, developing large projects in those languages is so much more inefficient that the extra effort for calling C++ functions from C or Fortran is absolutely justified. Stefanus Du Toit demonstrated in his Hourglass API an example of how to interface programs in C++ and other languages through a thin C API [12].
The elegant way of writing scientific software is to provide the best abstraction. A good implementation reduces the user interface to the essential behavior and omits all unnecessary commitments to technical details. Applications with a concise and intuitive interface can be as efficient as their ugly and detail-obsessed counterparts.
Our abstractions here are linear operators and vector spaces. What is important for the developer is how these abstractions are used, in our case, how a linear operator is applied on a vector. Let’s say the application is denoted by the symbol * as in L * v or A * x. Evidently, we expect that the result of this operation yields an object of a vector type (thus, the statement w= L * v; should compile) and that the mathematical properties of linearity hold. That is all that developers need to know for using a linear operator.
How the linear operator is stored internally is irrelevant for the correctness of the program—as long as the operation meets all mathematical requirements and the implementation has no accidental side effect like overwriting other objects’ memory. Therefore, two different implementations that provide the necessary interface and semantic behavior are interchangeable; i.e., the program still compiles and yields the same results. The different implementations can of course vary dramatically in their performance. For that reason, it is important that choosing the best implementation for a target platform or a specific application can be achieved with little (or no) program modifications on the application level.
This is why the most important benefit of classes in C++ for us is not the inheritance mechanisms (Chapter 6) but the ability to establish new abstractions and to provide alternative realizations for them. This chapter will lay the foundations for it, and we will elaborate on this programming style in the subsequent chapters with more advanced techniques.
C++: C++ Fundamentals, C++ Inventor - C++ Language Designer: Bjarne Stroustrup in 1985; C++ Keywords, C++ Built-In Data Types, C++ Data Structures (CPP Containers) - C++ Algorithms, C++ Syntax, C++ OOP - C++ Design Patterns, Clean C++ - C++ Style Guide, C++ Best Practices ( C++ Core Guidelines (CG)) - C++ BDD, C++ Standards ( C++ 23, C++ 20, C++ 17, C++ 14, C++ 11, C++ 03, C++ 98), Bjarne Stroustrup's C++ Glossary, CppReference.com, CPlusPlus.com, ISOcpp.org, C++ Compilers (Compiler Explorer, MinGW), C++ IDEs, C++ Development Tools, C++ Linter, C++ Debugging, C++ Modules ( C++20), C++ Packages, C++ Package Manager ( Conan - the C/C++ Package Manager), C++ Standard Library, C++ Libraries, C++ Frameworks, C++ DevOps - C++ SRE, C++ CI/CD ( C++ Build Pipeline), C++ Data Science - C++ DataOps, C++ Machine Learning, C++ Deep Learning, Functional C++, C++ Concurrency, C++ History, C++ Topics, C++ Bibliography, Manning C++ Series, C++ Courses, CppCon, C++ Research, C++ GitHub, Written in C++, C++ Popularity, C++ Awesome , C++ Versions. (navbar_cplusplus – see also navbar_cpp_containers, navbar_cppcon, navbar_cpp_core_guidelines, navbar_cpp23, navbar_cpp20, navbar_cpp17, navbar_cpp14, navbar_cpp11)
© 1994 - 2024 Cloud Monk Losang Jinpa or Fair Use. Disclaimers
SYI LU SENG E MU CHYWE YE. NAN. WEI LA YE. WEI LA YE. SA WA HE.