Philosophical Reflections in C++

Click the blue text to follow us

Introduction

“Before the program runs, the thought comes first.” In the realm of computer science, C++ occupies an important position with its unique philosophical system. C++ is a powerful yet complex programming language designed by Bjarne Stroustrup[1](Figure 1), which supports multiple programming styles. It is not only an inheritance and development of C and other programming languages but also a new reflection on the operational laws of the computer world.

C++ introduces concepts such as classes, inheritance, and polymorphism, which do not merely add functionality but promote a leap from procedural to object-oriented programming through a re-understanding of programming models. Behind every new feature lies a philosophical process of “negation of negation,” which signifies the inheritance and transcendence of old programming ideas.

Philosophical Reflections in C++

Figure 1: Bjarne Stroustrup, the father of C++, and his representative work

1. Characteristics of C++ Language

1.1. Encapsulation in C++

C++ introduces the mechanism of class encapsulation[2]. When we construct a class, encapsulation transforms the program into a black box that performs specific functions (Figure 2). Users do not need to concern themselves with the internal structure of the program; they only need to operate the external interface to complete tasks, significantly reducing the user’s burden and avoiding the risk of program tampering.

Marxist philosophy posits that the whole is not a mechanical sum of parts, but an organic unity formed by the internal connections and interactions of its parts[3].

The class encapsulation mechanism in C++ perfectly illustrates the dialectical relationship between the whole and its parts in materialist dialectics. When we encapsulate data members and member functions into a class, it is not a simple physical superposition but an organic combination achieved through access control. Using a biological metaphor, private members are like the nucleus protected by the cell membrane, while public interfaces serve as the channels for exchanging material and energy with the outside world. This combination of parts into an organic whole enables the program to operate in an orderly and efficient manner, much like a living cell.

Philosophical Reflections in C++

Figure 2: Illustration of encapsulation in C++

1.2. Inheritance in C++

In C++, we categorize and abstract everything in the world into specific classes, just as we abstract “animals with four legs, a long tail, and meowing” into “cats.” Within cats, there are white cats, black cats, and orange cats, leading us to further abstract “cats with black fur” into “black cats.” In the classes we abstract, “black cats” possess all the characteristics of “cats” but also have new features based on the cat class. In C++, we refer to this as “inheritance,” where “cat” is the base class and “black cat” is the derived class (Figure 3).

The development of things is achieved through the movement of their internal contradictions in a self-negating manner. The dialectical negation of things is not completed in one go but undergoes two negations and three stages: a systematic process of “affirmation—negation—negation of negation.” The negation of negation stage seems to be a “return” to the original starting point, but it is a “return” at a higher stage.

The unique inheritance system in C++ illustrates the unity of progress and twists in the development of things, confirming the law of negation of negation. The derived class inherits the characteristics of the base class but also develops new structures and functionalities. This is the negation of the base class. Meanwhile, the base class (utilizing virtual function tables and base class pointers) can point to and call the data and functionalities of derived class objects. This complex relationship and functional network create a new system that is neither the base class nor the derived class, elevating the inheritance system to a new height. This development law of negation of negation allows the code to maintain stability while achieving functional complexity, enabling object-oriented programming to spiral evolve through class inheritance and derivation.

Philosophical Reflections in C++

Figure 3: Illustration of inheritance in C++

2. Compilation Characteristics of C++

2.1. Type System in C++

The C++ language categorizes various data types in reality, similar to integers, small numbers, and letters in mathematics. For a program to run, it needs to know the type of data objects it is operating on and call the appropriate tools based on the specific type. Some data types are determined before the program runs (more accurately, during compilation), while others can only be determined during program execution. This approach saves efficiency and allows the program to better respond to environmental changes.

Truth possesses objectivity and absoluteness. The objectivity of truth refers to the correct reflection of the content of objective things and their laws, containing objective content that does not depend on people or human consciousness. The absoluteness of truth refers to the certainty of the unity of subjective and objective and the infinite development of truth: any truth marks the conformity of subjective and objective, contains objective content that does not depend on people or human consciousness, and has principled boundaries with errors; every step forward in understanding brings us closer to the infinitely developing material world.

In C++, static type checking is like the absolute truth for program execution, as it determines data types in advance during the compilation phase; while dynamic type conversion reflects the relativity of truth, seeking and confirming the final type of data at runtime through certain operators. This dynamic and static relationship, seemingly contradictory like a struggle between left and right hands, is in fact dialectically unified, continuously reflecting the law of unity of opposites.

2.2. Memory Management in C++

C++ uses pointers to operate on objects. When we store data in system memory, we often use pointers to manage them. Pointers include traditional pointers and smart pointers, which are fundamentally the same but serve different functions. Smart pointers are classes used to manage dynamically allocated memory, automatically releasing memory when the object’s lifecycle ends, while traditional pointers do not automatically release memory.

The law of unity of opposites is the essence and core of materialist dialectics. Opposing sides in contradiction both struggle and unify, thus driving the development of things. The unity of contradictions refers to the nature and trend of mutual dependence and interpenetration between opposing sides; the struggle of contradictions refers to the nature and trend of mutual exclusion and separation between opposing sides. The combination of the unity and struggle of contradictions constitutes the fundamental driving force of development.

Traditional pointers grant programmers a high degree of autonomy, but this comes with security risks; smart pointers accept system constraints and control, making programmers’ operations more convenient and secure. Just as the law of unity of opposites emphasizes: opposing sides are both mutually exclusive and mutually dependent, possessing both struggle and unity. Traditional pointers and smart pointers form a pair of contradictions, and during program execution, the unity and struggle of both sides combine to manage memory.

Philosophical Reflections in C++

Figure 4: Illustration of memory allocation

3. Programming Characteristics of C++

3.1. The Game Between Efficiency and Safety

In the process of learning and using C++, the program’s “efficiency” and “safety” are like “fish” and “bear’s paw,” which cannot be obtained simultaneously, and can even be considered a contradictory existence. This contradiction drives the development of the C++ language itself, giving birth to an operational method that combines both “efficiency” and “safety” known as “move semantics.”

Contradiction is a philosophical category that reflects the dialectical unity of internal or external relationships between things. The unity of contradiction refers to the nature and trend of mutual dependence and interpenetration between opposing sides, while the struggle of contradiction refers to the nature and trend of mutual exclusion and separation between opposing sides.

The subtle relationship between runtime efficiency and memory safety in C++ constitutes a pair of contradictions, highlighting the basic properties of both unity and struggle. Efficiency and safety, as mutually dependent sides, must coexist within the system. At the same time, efficiency and memory safety can convert into each other under certain conditions. For example, using array copy constructors is more efficient but consumes redundant memory. This mutual dependence and interpenetration reflect the unity of contradictions. Excessive pursuit of efficiency can expose memory to danger, while excessive caution in pursuing safety can make the program precarious, failing to meet the practical needs for program efficiency. Efficiency and safety are like the two ends of a balance; excessive emphasis on one side (efficiency) will directly suppress the other side (safety), reflecting the struggle of contradictions. Developers must pay attention to memory allocation while maximizing runtime efficiency, as the unity and struggle of contradictions are interconnected and complementary.

Philosophical Reflections in C++

Figure 5: The relationship between safety and efficiency

3.2. The Combination of Abstraction and Concreteness

“Generic programming” in C++ refers to the process of extracting common features from a series of problems and designing a general solution, similar to the saying “one solution for many problems” we often hear in life. Another concept in C++, “template specialization,” refers to modifying the general solution for different special cases, allowing them to adjust according to the specific problems to be solved, thus solving problems more efficiently and effectively. C++ programming typically goes through the design of “generic programming” followed by “template specialization.”

The dialectical movement of practice and understanding is a leap from sensory understanding to rational understanding, and then back to practice, a cyclical and infinite dialectical development process of practice, understanding, and re-practice.

In C++, “generic programming” abstracts and categorizes specific problems, then designs general solutions, greatly improving code efficiency and reducing the programming burden on developers. Meanwhile, “template specialization” returns abstraction to concrete reality, designing targeted solutions for specific problems, enhancing the program’s ability to respond to special issues and improving its effectiveness and adaptability. This “concrete—abstract—concrete” programming design process confirms the basic laws of Marxist epistemology. Viewing generic programming as understanding and template specialization as practice, the process of understanding deepens on the basis of practice, reflecting the dialectical movement from practice to understanding and back to practice[3].

Conclusion

Bjarne Stroustrup, the father of C++, once said: “The design of C++ is a choice, not a coincidence.” This language shines with the wisdom of dialectics: the opposition and unity of pointers and references, the quantitative and qualitative changes presented during compilation and runtime, and the negation of negation relationship between encapsulation and inheritance. In the lines of code, we see not only the implementation of programs but also the way humans understand and transform the world.

Image materials are sourced from the internet; please contact us if there are any infringements.

References

[1] Stroustrup, B. (2013). The C++ Programming Language. Addison-Wesley Professional.

[2] Gamma, E., Helm, R., Johnson, R., & Vlissides, J. (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley.

[3] Compilation Group. Basic Principles of Marxism [M]. Beijing: Higher Education Press, 2023.

[4] Sutter, H., & Alexandrescu, A. (2004). *C++ Coding Standards: 101 Rules, Guidelines, and Best Practices*. Addison-Wesley.

Philosophical Reflections in C++Philosophical Reflections in C++

Leave a Comment