C++ Object-Oriented Programming: From Built-in Types to Custom Types

The Essence of Object-Oriented Programming

The core idea of Object-Oriented Programming (OOP) is to simulate concepts from the real world by creating custom data types, allowing data types to perfectly match the data being processed. This way of thinking makes the code more intuitive and easier to maintain.

C++ Built-in Basic Types

Integer Types

#include <iostream>
#include <climits>  // View type limits

using namespace std;

int main() {
    // Integer type example
    short smallNumber = 100;           // Short integer, usually 16 bits
    int normalNumber = 100000;         // Integer, usually 32 bits
    long largeNumber = 1000000000L;    // Long integer, usually 32 or 64 bits
    long long hugeNumber = 1000000000000LL; // Long long integer, usually 64 bits
    
    // View the range of each type
    cout << "short range: " << SHRT_MIN << " to " << SHRT_MAX << endl;
    cout << "int range: " << INT_MIN << " to " << INT_MAX << endl;
    cout << "long range: " << LONG_MIN << " to " << LONG_MAX << endl;
    
    // Signed and unsigned types
    signed int negativeNumber = -100;      // Signed integer (default)
    unsigned int positiveOnly = 200;       // Unsigned integer, can only store non-negative numbers
    
    cout << "Signed integer: " << negativeNumber << endl;
    cout << "Unsigned integer: " << positiveOnly << endl;
    
    return 0;
}

Floating Point Types

#include <iostream>
#include <iomanip>  // Control output format
#include <cmath>    // Math functions

using namespace std;

int main() {
    // Floating point type example
    float simplePrecision = 3.14159f;          // Single precision floating point
    double normalPrecision = 3.1415926535;     // Double precision floating point (default)
    long double highPrecision = 3.141592653589793238L; // High precision floating point
    
    // Set output precision
    cout << fixed << setprecision(10);
    
    cout << "float precision: " << simplePrecision << endl;
    cout << "double precision: " << normalPrecision << endl;
    cout << "long double precision: " << highPrecision << endl;
    
    // Scientific notation
    double largeNumber = 1.5e8;    // 1.5 × 10^8
    double smallNumber = 1.5e-8;   // 1.5 × 10^-8
    
    cout << scientific;
    cout << "Large number in scientific notation: " << largeNumber << endl;
    cout << "Small number in scientific notation: " << smallNumber << endl;
    
    return 0;
}

Variables and Basic Operations

#include <iostream>

using namespace std;

int main() {
    // Variable declaration and initialization
    int age = 25;                   // Declare and initialize
    double salary;                  // Declaration
    salary = 50000.50;              // Subsequent assignment
    
    const double PI = 3.14159;      // Constant, cannot be modified
    
    // Arithmetic operations
    int a = 10, b = 3;
    cout << "a = " << a << ", b = " << b << endl;
    cout << "Addition: " << a + b << endl;
    cout << "Subtraction: " << a - b << endl;
    cout << "Multiplication: " << a * b << endl;
    cout << "Division: " << a / b << endl;        // Integer division
    cout << "Modulus: " << a % b << endl;
    
    // Floating point operations
    double x = 10.0, y = 3.0;
    cout << "Floating point division: " << x / y << endl;
    
    // Compound assignment operators
    int count = 5;
    count += 3;     // Equivalent to count = count + 3
    cout << "After count += 3: " << count << endl;
    
    // Increment and decrement
    int number = 5;
    cout << "Original value: " << number << endl;
    cout << "Post-increment: " << number++ << endl;  // Use first, then increase
    cout << "Current value: " << number << endl;
    cout << "Pre-increment: " << ++number << endl;  // Increase first, then use
    
    return 0;
}

Type Conversion

#include <iostream>

using namespace std;

int main() {
    // Implicit type conversion
    int integer = 10;
    double decimal = 3.14;
    
    double result1 = integer + decimal;  // int automatically converted to double
    cout << "int + double = " << result1 << endl;
    
    // Explicit type conversion (C-style)
    double pi = 3.14159;
    int intPi = (int)pi;                 // Force conversion to int, losing the decimal part
    cout << "double 3.14159 converted to int: " << intPi << endl;
    
    // C++ style type conversion
    double price = 19.99;
    int intPrice = static_cast<int>(price);  // Static type conversion
    cout << "static_cast<int>(19.99) = " << intPrice << endl;
    
    // Conversion between characters and integers
    char letter = 'A';
    int asciiValue = static_cast<int>(letter);
    cout << "ASCII value of 'A': " << asciiValue << endl;
    
    int number = 66;
    char character = static_cast<char>(number);
    cout << "Character corresponding to ASCII 66: " << character << endl;
    
    return 0;
}

Designing Custom Data Types

Now let’s see how to create our own data types based on these basic types:

#include <iostream>
#include <string>

using namespace std;

// Custom data type: Bank Account
class BankAccount {
private:
    string accountNumber;    // Account number
    string ownerName;        // Account holder
    double balance;          // Balance
    
public:
    // Constructor
    BankAccount(const string&amp; accNum, const string&amp; name, double initialBalance) {
        accountNumber = accNum;
        ownerName = name;
        balance = initialBalance;
    }
    
    // Deposit method
    void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            cout << "Successfully deposited: $" << amount << endl;
        } else {
            cout << "Deposit amount must be greater than 0" << endl;
        }
    }
    
    // Withdraw method
    bool withdraw(double amount) {
        if (amount > 0 &amp;&amp; amount <= balance) {
            balance -= amount;
            cout << "Successfully withdrew: $" << amount << endl;
            return true;
        } else {
            cout << "Withdrawal failed: Insufficient balance or invalid amount" << endl;
            return false;
        }
    }
    
    // Display account information
    void displayInfo() const {
        cout << "Account number: " << accountNumber << endl;
        cout << "Account holder: " << ownerName << endl;
        cout << "Current balance: $" << balance << endl;
    }
    
    // Get balance
    double getBalance() const {
        return balance;
    }
};

int main() {
    // Using custom data type
    BankAccount myAccount("123456789", "Zhang San", 1000.0);
    
    cout << "=== Initial Account Information ===" << endl;
    myAccount.displayInfo();
    
    cout << "\n=== Performing Transactions ===" << endl;
    myAccount.deposit(500.0);
    myAccount.withdraw(200.0);
    myAccount.withdraw(2000.0);  // This will fail
    
    cout << "\n=== Final Account Information ===" << endl;
    myAccount.displayInfo();
    
    return 0;
}

More Complex Custom Type Example

#include <iostream>
#include <string>
#include <vector>

using namespace std;

// Custom data type: Student Grade Management System
class Student {
private:
    string name;
    int id;
    vector<double> grades;  // Using composite type to store list of grades
    
public:
    Student(const string&amp; studentName, int studentId) 
        : name(studentName), id(studentId) {}
    
    // Add grade
    void addGrade(double grade) {
        if (grade >= 0 &amp;&amp; grade <= 100) {
            grades.push_back(grade);
            cout << "Added grade for " << name << ": " << grade << endl;
        } else {
            cout << "Invalid grade: " << grade << " (Grade should be between 0-100)" << endl;
        }
    }
    
    // Calculate average
    double calculateAverage() const {
        if (grades.empty()) {
            return 0.0;
        }
        
        double sum = 0.0;
        for (double grade : grades) {
            sum += grade;
        }
        return sum / grades.size();
    }
    
    // Display student information
    void displayInfo() const {
        cout << "Student ID: " << id << endl;
        cout << "Name: " << name << endl;
        cout << "Grades: ";
        for (double grade : grades) {
            cout << grade << " ";
        }
        cout << endl;
        cout << "Average: " << calculateAverage() << endl;
    }
};

int main() {
    // Create student objects
    Student student1("Li Si", 1001);
    Student student2("Wang Wu", 1002);
    
    // Add grades
    student1.addGrade(85.5);
    student1.addGrade(92.0);
    student1.addGrade(78.5);
    
    student2.addGrade(90.0);
    student2.addGrade(88.5);
    student2.addGrade(95.0);
    
    // Display information
    cout << "=== Student Information ===" << endl;
    student1.displayInfo();
    cout << endl;
    student2.displayInfo();
    
    return 0;
}

Key Points Summary

  1. Understanding Basic Types: Integer and floating-point types are the foundation for building more complex types
  2. Type Matching: Choosing the right data type can make the code more efficient and safer
  3. Type Conversion: Understanding the rules and risks of implicit and explicit type conversion
  4. Custom Types: Encapsulating data and operations together using classes
  5. Data Abstraction: Hiding implementation details while exposing necessary interfaces

By correctly designing your own data types, you can create code that is easier to understand and maintain, which is the core value of object-oriented programming.

Leave a Comment