C++ Series: Getting Started — An Introduction to C++ (Part 1)

Time: Column:Mobile & Frontend views:224

In the vast ocean of programming languages, C++ stands out with its powerful capabilities and flexibility. Since it was developed by Bjarne Stroustrup at Bell Labs in 1979, C++ has gradually become the language of choice for high-performance applications and system programming. It not only inherits the efficient characteristics of the C language but also introduces the concept of object-oriented programming, making software development more structured and maintainable.

C++ has widespread applications ranging from game development, graphics processing, to building operating systems and large software systems. With its rich standard library and powerful template mechanism, C++ enables developers to write efficient and reusable code. This blog will take you through the basic concepts of C++, its development history, the importance of learning this language, and its application scenarios. Whether you are a beginner or an experienced developer, C++ will offer you new perspectives and skills for your programming journey.


1. Origins and Development History of C++

1.1 Origins

The origins of C++ can be traced back to 1979 when Bjarne Stroustrup developed it at Bell Labs. Faced with the limitations of existing languages like C for complex software development, he introduced object-oriented features on top of C in 1983, officially naming it C++. The language gradually gained adoption in academia and industry and became a teaching language in many universities.

C++ Series: Getting Started — An Introduction to C++ (Part 1)

1.2 C++ Version Updates

In 1989, the standardization of C++ began, with the first draft of the standard presented in 1994, which introduced the Standard Template Library (STL), greatly enhancing C++'s functionality. After several discussions, the ANSI/ISO standard was officially released in 1998, solidifying C++'s position in programming languages. Since then, C++ has undergone multiple updates such as C++11, C++14, C++17, and C++20, continuing to evolve to meet modern development needs.

C++ Series: Getting Started — An Introduction to C++ (Part 1)


2. Applications of C++ in the Workplace

C++ is used in many fields, including server-side applications, game engines, machine learning engines, audio and video processing, embedded software, telecom equipment, financial applications, core libraries, operating systems, compilers, infrastructure, tools, hardware interaction, and more.

  • Large system software development: such as compilers, databases, operating systems, and browsers.

  • Audio and video processing: Common open-source libraries and solutions include FFmpeg, WebRTC, Mediasoup, ijkplayer. C++ is the main technology stack for audio and video development.

  • PC client development: Typically involves developing desktop software for Windows, such as WPS. The technology stack is generally C++ and QT. QT is a cross-platform C++ graphical user interface (GUI) framework.

  • Server-side development: Large applications and high-concurrency backend services for network connections. Java is also widely used here, while C++ is employed for areas requiring higher performance, such as game services, streaming services, and high-frequency trading services.

  • Game engine development: Many game engines are developed using C++. Game development requires understanding C++ fundamentals, data structures, graphics knowledge, and mastering game engines and frameworks. Open-source engine implementations like UE4 and Cocos2d-x can be studied.

  • Embedded development: Involves embedding a computing control board into devices like smart wristbands, cameras, robots, smart speakers, door control systems, and car systems. Embedded development includes application and driver development.

  • Machine learning engines: Many core machine learning algorithms are implemented in C++, with Python used for higher-level wrappers. If you want to work on machine learning system development, learning C++ is essential.

  • Testing development/Testing: Every company has both development and testing teams. Testing includes test development and functional testing. Test developers typically use tools like Selenium and JMeter, designing test cases and writing scripts for automated testing and performance testing.


3. Recommendations for Getting Started with C++

C++ Series: Getting Started — An Introduction to C++ (Part 1)

3.1 Reference Documents

Note: The first link is not the official C++ documentation, as it only updates to C++11 but presents content in a more readable format. The latter two are official C++ documentation in Chinese and English, respectively, and provide comprehensive information updated to the latest C++ standards, though they are not as easy to read as the first.

3.2 Recommended Books

Beginner Level

  1. Programming: Principles and Practice Using C++ by Bjarne Stroustrup

  2. C++ Primer by Stanley B. Lippman, Josée Lajoie, Barbara E. Moo

  3. Accelerated C++: Practical Programming by Example by Andrew Koenig and Barbara E. Moo

Intermediate Level

  1. Effective C++ by Scott Meyers

  2. More Effective C++ by Scott Meyers

  3. The C++ Standard Library: A Tutorial and Reference by Nicolai M. Josuttis

Advanced Level

  1. The C++ Programming Language by Bjarne Stroustrup

  2. C++ Concurrency in Action by Anthony Williams

  3. Modern C++ Design by Andrei Alexandrescu

  4. C++ Templates: The Complete Guide by David Vandevoorde, Nicolai M. Josuttis, Doug Gregor

Specialized Topics

  1. C++17 in Detail by Bartłomiej Filipek (for modern C++ standards)

  2. Effective Modern C++ by Scott Meyers (focus on C++11 and C++14)

  3. A Tour of C++ by Bjarne Stroustrup (overview of modern C++ features)

This list covers foundational learning, advanced techniques, and specialized areas such as concurrency, templates, and modern C++ standards.


4. C++ First Program

4.1 C Language Approach

C++ is compatible with most of the C language syntax, so a C program like "Hello World" can still run in C++. In C++, the file extension must be changed to .cpp, and the compiler will recognize it and call the C++ compiler. In Linux, g++ should be used instead of gcc.

#include<stdio.h>
int main()
{
    printf("hello world!");
    return 0;
}

4.2 C++ Approach

#include<iostream> 
int main() {
    std::cout << "hello world" << std::endl;
    return 0;
}

5. Namespaces

5.1 Why Use Namespaces

In C/C++, there are many variables, functions, and classes, and their names are all in the global scope, which may cause conflicts. The purpose of using namespaces is to localize the names of identifiers to avoid naming conflicts or pollution. The namespace keyword addresses this issue.

5.2 Defining a Namespace

A namespace is a mechanism in C++ for organizing code. It allows related classes, functions, variables, etc., to be grouped together in a namespace to avoid name conflicts and improve readability. It is defined with the namespace keyword as follows:

namespace NamespaceName {
    int variable;
    
    void function() {
        // Function implementation
    }
}

In this example, we define a namespace called NamespaceName containing an integer variable and a function.

5.3 Key Features

  • Scope Independence: A namespace creates an independent scope where the members defined within it do not interfere with members in the global scope or other namespaces.

  • Resolving Name Conflicts: Different namespaces can define the same variable, function, etc., without conflict. For example, namespace A { void func(); } and namespace B { void func(); } can coexist.

  • Nesting: Namespaces can be nested to better organize code.

namespace Outer {
    namespace Inner {
        void innerFunction() {
            // Implementation
        }
    }
}
  • Cross-file Sharing: The same namespace can be defined across multiple files in a project and will be treated as a single namespace without conflict.

  • Standard Library Namespace: All elements of the C++ standard library are included in the std namespace, such as std::cout and std::vector.

5.4 Usage Example

To use a member from a namespace:

  • Using the scope resolution operator:

NamespaceName::function();
  • Using using declaration:

using namespace NamespaceName; 
function(); // Direct call

Note: The using directive expands all members of a namespace, which is not recommended for larger projects due to potential conflicts. It is best to use using for specific, conflict-free members in smaller programs.


6. C++ Input & Output

  1. Concept Overview

    • <iostream> stands for "Input Output Stream" and is the standard library for input and output streams. It defines standard input and output objects.

    • std::cin is an object of the istream class, mainly used for the standard input stream of narrow characters (of type char).

    • std::cout is an object of the ostream class, mainly used for the standard output stream of narrow characters.

    • std::endl is a function that, when inserted into a stream, adds a newline character and flushes the buffer.

    • << is the stream insertion operator, and >> is the stream extraction operator. (In C, these operators are also used for bitwise left/right shifts.)

    • Using C++ input and output is more convenient, as there is no need to manually specify formats like printf/scanf. C++ input and output can automatically detect variable types (this is essentially achieved through function overloading, which we will discuss later). The most important feature is that C++ streams better support input and output for user-defined types.

    • IO streams involve classes and objects, operator overloading, inheritance, and many other object-oriented concepts. Since we haven’t covered these topics yet, we can only briefly introduce how to use C++ IO streams here. We will have a dedicated section later to discuss the IO stream library in detail.

    • cout, cin, endl, etc., belong to the C++ Standard Library, which is contained within a namespace called std (for "standard"). Therefore, we must use the namespace to access them.

    • In daily practice, we can use using namespace std, but in real project development, it’s not recommended.

    • We didn’t include <stdio.h>, but printf and scanf can also be used, as they are indirectly included when we include <iostream>. This is true for Visual Studio compilers; other compilers may throw errors.

  2. Code Example

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

int main()
{
    // To improve IO efficiency in scenarios with high IO demands, such as certain competitive programming problems involving large inputs, add the following three lines:
    ios_base::sync_with_stdio(false); 
    cin.tie(nullptr);
    cout.tie(nullptr);

    int a = 10;
    double b = 1.1;
    char c = 'a';

    cout << a << " " << b << " " << c << endl;
    std::cout << a << " " << b << " " << c << std::endl;
    scanf_s("%d%lf", &a, &b);
    printf("%d %lf\n", a, b);

    // Automatically detect variable types
    cin >> a >> b >> c;
    cout << a << " " << b << " " << c << endl;
    return 0;
}

7. Default Parameters

  1. DefinitionDefault parameters in C++ refer to the default values specified for parameters when declaring or defining a function. If no arguments are provided for these parameters during function calls, the default values are automatically used. This feature enhances the flexibility and ease of use of functions. Here's a detailed introduction to C++ default parameters:

    • Fully defaulted means all parameters are given default values.

    • Partially defaulted means some parameters are given default values. C++ requires that partial default parameters be assigned in a continuous order from right to left; there can be no gaps between default values.

    • Default parameters can be fully defaulted or partially defaulted.

    • When calling a function with default parameters, C++ requires arguments to be passed from left to right; you cannot skip over any arguments.

    • When function declarations and definitions are separated, default parameters can only appear in the function declaration, not in both the declaration and definition.

  2. Code Example

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

// Fully defaulted
void Func1(int a = 10, int b = 20, int c = 30)
{
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl << endl;
}

// Partially defaulted
void Func2(int a, int b = 10, int c = 20)
{
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl << endl;
}

int main()
{
    Func1(); // Equivalent to func1(10, 20, 30)
    Func1(1); // Equivalent to func1(1, 20, 30)
    Func1(1, 2); // Equivalent to func1(1, 2, 30)
    Func1(1, 2, 3); // Equivalent to func1(1, 2, 3)

    Func2(100); // Equivalent to func2(100, 10, 20)
    Func2(100, 200); // Equivalent to func2(100, 200, 20)
    Func2(100, 200, 300); // Equivalent to func2(100, 200, 300)

    return 0;
}

8. Function Overloading

  1. Basic Concept of Function OverloadingIn C++, function overloading allows us to define multiple functions with the same name, but the parameter lists (number, type, or order of parameters) must differ. The compiler determines which function to call based on the arguments passed.

    The core idea behind function overloading is the difference in parameter lists. Here are some examples of overloaded functions:

void print(int num);
void print(double num);
void print(const char* str);

In the examples above, we have defined three print functions, each with different parameter lists, so they are treated as separate functions.

  1. Rules of Function Overloading

    • Different number of parameters: Functions can have different numbers of parameters.

    • Different parameter types: Functions can have the same number but different types of parameters.

    • Different parameter order: If the number and types of parameters are the same, but their order differs, they can also be overloaded.

  2. Code Example

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

// 1. Different parameter types
int Add(int x, int y)
{
    cout << "int Add(int x, int y)" << endl;
    return x + y;
}

double Add(double x, double y)
{
    cout << "double Add(double x, double y)" << endl;
    return x + y;
}

// 2. Different number of parameters
void fun()
{
    cout << "void fun()" << endl;
}

void fun(int a)
{
    cout << "void fun(int a)" << endl;
}

// 3. Different parameter order
void func(int a, double b)
{
    cout << "void func(int a, double b)" << endl;
}

void func(double a, int b)
{
    cout << "void func(double a, int b)" << endl;
}

int main()
{
    Add(10, 20);
    Add(10.1, 20.2);

    fun();
    fun(10);

    func(10, 2.2);
    func(10.1, 22);

    return 0;
}