Skip to content

面向对象

概述

面向对象编程(OOP)是C++的核心特性,包括封装、继承和多态三大特性。

类与对象

基本定义

cpp
#include <iostream>
#include <string>

using namespace std;

class Person {
public:
    string name;
    int age;

    void introduce() {
        cout << "我叫" << name << ",今年" << age << "岁。" << endl;
    }
};

int main() {
    Person p1;
    p1.name = "张三";
    p1.age = 25;
    p1.introduce();

    Person p2;
    p2.name = "李四";
    p2.age = 30;
    p2.introduce();

    return 0;
}

构造函数

cpp
#include <iostream>
#include <string>

using namespace std;

class Student {
public:
    string name;
    int age;
    double score;

    Student() {
        name = "未知";
        age = 0;
        score = 0.0;
        cout << "默认构造函数被调用" << endl;
    }

    Student(string n, int a, double s) {
        name = n;
        age = a;
        score = s;
        cout << "带参数构造函数被调用" << endl;
    }

    void display() {
        cout << "姓名: " << name << ", 年龄: " << age
             << ", 成绩: " << score << endl;
    }
};

int main() {
    Student s1;
    s1.display();

    Student s2("张三", 20, 85.5);
    s2.display();

    Student s3 = Student("李四", 22, 90.0);
    s3.display();

    return 0;
}

析构函数

cpp
#include <iostream>
#include <string>

using namespace std;

class Resource {
public:
    string name;

    Resource(string n) : name(n) {
        cout << "构造: " << name << endl;
    }

    ~Resource() {
        cout << "析构: " << name << endl;
    }
};

int main() {
    cout << "程序开始" << endl;

    {
        Resource r1("资源1");
        Resource r2("资源2");
    }

    cout << "程序结束" << endl;

    return 0;
}

成员初始化列表

cpp
#include <iostream>
#include <string>

using namespace std;

class Rectangle {
public:
    const double width;
    const double height;
    double area;

    Rectangle(double w, double h)
        : width(w), height(h), area(w * h) {
        cout << "矩形创建成功" << endl;
    }

    void display() {
        cout << "宽: " << width << ", 高: " << height
             << ", 面积: " << area << endl;
    }
};

int main() {
    Rectangle rect(5.0, 3.0);
    rect.display();

    return 0;
}

访问控制

public、private、protected

cpp
#include <iostream>
#include <string>

using namespace std;

class BankAccount {
private:
    string accountNumber;
    double balance;

protected:
    string ownerName;

public:
    BankAccount(string owner, string accNum, double initialBalance)
        : ownerName(owner), accountNumber(accNum), balance(initialBalance) {}

    void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            cout << "存款成功: " << amount << endl;
        }
    }

    void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            cout << "取款成功: " << amount << endl;
        } else {
            cout << "取款失败: 余额不足或金额无效" << endl;
        }
    }

    double getBalance() const {
        return balance;
    }

    void displayInfo() {
        cout << "户主: " << ownerName << endl;
        cout << "账号: " << accountNumber << endl;
        cout << "余额: " << balance << endl;
    }
};

int main() {
    BankAccount account("张三", "1234567890", 1000);

    account.displayInfo();
    account.deposit(500);
    account.withdraw(200);
    account.displayInfo();

    return 0;
}

拷贝控制

拷贝构造函数

cpp
#include <iostream>
#include <string>

using namespace std;

class StringWrapper {
public:
    string *data;

    StringWrapper(const string &s) {
        data = new string(s);
        cout << "构造: " << *data << endl;
    }

    StringWrapper(const StringWrapper &other) {
        data = new string(*other.data);
        cout << "拷贝构造: " << *data << endl;
    }

    ~StringWrapper() {
        cout << "析构: " << *data << endl;
        delete data;
    }

    void display() {
        cout << "内容: " << *data << endl;
    }
};

int main() {
    StringWrapper s1("Hello");
    StringWrapper s2 = s1;
    StringWrapper s3(s1);

    s1.display();
    s2.display();
    s3.display();

    return 0;
}

拷贝赋值运算符

cpp
#include <iostream>
#include <string>

using namespace std;

class MyString {
public:
    string *data;

    MyString(const string &s = "") {
        data = new string(s);
    }

    MyString(const MyString &other) {
        data = new string(*other.data);
    }

    MyString& operator=(const MyString &other) {
        if (this != &other) {
            delete data;
            data = new string(*other.data);
        }
        return *this;
    }

    ~MyString() {
        delete data;
    }

    void display() {
        cout << *data << endl;
    }
};

int main() {
    MyString s1("Hello");
    MyString s2("World");

    cout << "赋值前:" << endl;
    s1.display();
    s2.display();

    s2 = s1;

    cout << "赋值后:" << endl;
    s1.display();
    s2.display();

    return 0;
}

静态成员

静态数据成员

cpp
#include <iostream>

using namespace std;

class Counter {
public:
    static int count;

    Counter() {
        count++;
        cout << "创建对象,当前数量: " << count << endl;
    }

    ~Counter() {
        count--;
        cout << "销毁对象,当前数量: " << count << endl;
    }

    static int getCount() {
        return count;
    }
};

int Counter::count = 0;

int main() {
    cout << "初始数量: " << Counter::getCount() << endl;

    Counter c1;
    Counter c2;
    {
        Counter c3;
    }

    cout << "最终数量: " << Counter::getCount() << endl;

    return 0;
}

友元

友元函数

cpp
#include <iostream>

using namespace std;

class Box {
private:
    double width;
    double height;

public:
    Box(double w, double h) : width(w), height(h) {}

    friend double getArea(const Box &box);
    friend void displayBox(const Box &box);
};

double getArea(const Box &box) {
    return box.width * box.height;
}

void displayBox(const Box &box) {
    cout << "宽: " << box.width << ", 高: " << box.height << endl;
}

int main() {
    Box box(5.0, 3.0);
    displayBox(box);
    cout << "面积: " << getArea(box) << endl;

    return 0;
}

友元类

cpp
#include <iostream>

using namespace std;

class Engine;

class Car {
private:
    string brand;
    int speed;

public:
    Car(string b, int s) : brand(b), speed(s) {}

    friend class Engine;
};

class Engine {
public:
    void displayCarInfo(const Car &car) {
        cout << "品牌: " << car.brand << ", 速度: " << car.speed << endl;
    }

    void accelerate(Car &car, int increment) {
        car.speed += increment;
        cout << "加速后速度: " << car.speed << endl;
    }
};

int main() {
    Car car("Toyota", 100);
    Engine engine;

    engine.displayCarInfo(car);
    engine.accelerate(car, 20);
    engine.displayCarInfo(car);

    return 0;
}

运算符重载

基本运算符

cpp
#include <iostream>

using namespace std;

class Complex {
public:
    double real;
    double imag;

    Complex(double r = 0, double i = 0) : real(r), imag(i) {}

    Complex operator+(const Complex &other) const {
        return Complex(real + other.real, imag + other.imag);
    }

    Complex operator-(const Complex &other) const {
        return Complex(real - other.real, imag - other.imag);
    }

    Complex operator*(const Complex &other) const {
        return Complex(
            real * other.real - imag * other.imag,
            real * other.imag + imag * other.real
        );
    }

    bool operator==(const Complex &other) const {
        return real == other.real && imag == other.imag;
    }

    friend ostream& operator<<(ostream &os, const Complex &c);
};

ostream& operator<<(ostream &os, const Complex &c) {
    os << c.real;
    if (c.imag >= 0) os << "+";
    os << c.imag << "i";
    return os;
}

int main() {
    Complex c1(3, 4);
    Complex c2(1, 2);

    cout << "c1 = " << c1 << endl;
    cout << "c2 = " << c2 << endl;
    cout << "c1 + c2 = " << (c1 + c2) << endl;
    cout << "c1 - c2 = " << (c1 - c2) << endl;
    cout << "c1 * c2 = " << (c1 * c2) << endl;
    cout << "c1 == c2: " << (c1 == c2 ? "true" : "false") << endl;

    return 0;
}

下标运算符

cpp
#include <iostream>

using namespace std;

class IntArray {
private:
    int *data;
    int size;

public:
    IntArray(int s) : size(s) {
        data = new int[size];
        for (int i = 0; i < size; i++) {
            data[i] = 0;
        }
    }

    ~IntArray() {
        delete[] data;
    }

    int& operator[](int index) {
        if (index < 0 || index >= size) {
            throw out_of_range("索引越界");
        }
        return data[index];
    }

    const int& operator[](int index) const {
        if (index < 0 || index >= size) {
            throw out_of_range("索引越界");
        }
        return data[index];
    }

    int getSize() const { return size; }
};

int main() {
    IntArray arr(5);

    for (int i = 0; i < arr.getSize(); i++) {
        arr[i] = i * 10;
    }

    for (int i = 0; i < arr.getSize(); i++) {
        cout << "arr[" << i << "] = " << arr[i] << endl;
    }

    return 0;
}

继承

基本继承

cpp
#include <iostream>
#include <string>

using namespace std;

class Animal {
protected:
    string name;

public:
    Animal(string n) : name(n) {}

    void eat() {
        cout << name << "正在吃东西" << endl;
    }

    void sleep() {
        cout << name << "正在睡觉" << endl;
    }

    virtual void speak() {
        cout << name << "发出声音" << endl;
    }
};

class Dog : public Animal {
public:
    Dog(string n) : Animal(n) {}

    void speak() override {
        cout << name << "汪汪叫" << endl;
    }

    void fetch() {
        cout << name << "正在捡球" << endl;
    }
};

class Cat : public Animal {
public:
    Cat(string n) : Animal(n) {}

    void speak() override {
        cout << name << "喵喵叫" << endl;
    }

    void climb() {
        cout << name << "正在爬树" << endl;
    }
};

int main() {
    Dog dog("旺财");
    Cat cat("咪咪");

    dog.eat();
    dog.speak();
    dog.fetch();

    cout << "---" << endl;

    cat.eat();
    cat.speak();
    cat.climb();

    return 0;
}

多重继承

cpp
#include <iostream>
#include <string>

using namespace std;

class Flyable {
public:
    virtual void fly() {
        cout << "正在飞行" << endl;
    }
};

class Swimmable {
public:
    virtual void swim() {
        cout << "正在游泳" << endl;
    }
};

class Duck : public Flyable, public Swimmable {
private:
    string name;

public:
    Duck(string n) : name(n) {}

    void fly() override {
        cout << name << "正在飞翔" << endl;
    }

    void swim() override {
        cout << name << "正在游泳" << endl;
    }

    void quack() {
        cout << name << "嘎嘎叫" << endl;
    }
};

int main() {
    Duck duck("唐老鸭");

    duck.fly();
    duck.swim();
    duck.quack();

    return 0;
}

多态

虚函数

cpp
#include <iostream>
#include <string>
#include <vector>
#include <memory>

using namespace std;

class Shape {
public:
    virtual double area() = 0;
    virtual double perimeter() = 0;
    virtual void display() = 0;
    virtual ~Shape() {}
};

class Rectangle : public Shape {
private:
    double width, height;

public:
    Rectangle(double w, double h) : width(w), height(h) {}

    double area() override {
        return width * height;
    }

    double perimeter() override {
        return 2 * (width + height);
    }

    void display() override {
        cout << "矩形: 宽=" << width << ", 高=" << height << endl;
    }
};

class Circle : public Shape {
private:
    double radius;

public:
    Circle(double r) : radius(r) {}

    double area() override {
        return 3.14159 * radius * radius;
    }

    double perimeter() override {
        return 2 * 3.14159 * radius;
    }

    void display() override {
        cout << "圆形: 半径=" << radius << endl;
    }
};

int main() {
    vector<unique_ptr<Shape>> shapes;

    shapes.push_back(make_unique<Rectangle>(5, 3));
    shapes.push_back(make_unique<Circle>(4));
    shapes.push_back(make_unique<Rectangle>(2, 6));

    for (const auto &shape : shapes) {
        shape->display();
        cout << "面积: " << shape->area() << endl;
        cout << "周长: " << shape->perimeter() << endl;
        cout << "---" << endl;
    }

    return 0;
}

纯虚函数与抽象类

cpp
#include <iostream>
#include <string>

using namespace std;

class Vehicle {
protected:
    string brand;
    int speed;

public:
    Vehicle(string b, int s) : brand(b), speed(s) {}

    virtual void start() = 0;
    virtual void stop() = 0;
    virtual void accelerate(int increment) = 0;

    void displayInfo() {
        cout << "品牌: " << brand << ", 速度: " << speed << endl;
    }

    virtual ~Vehicle() {}
};

class Car : public Vehicle {
public:
    Car(string b, int s) : Vehicle(b, s) {}

    void start() override {
        cout << brand << "汽车启动" << endl;
    }

    void stop() override {
        cout << brand << "汽车停止" << endl;
        speed = 0;
    }

    void accelerate(int increment) override {
        speed += increment;
        cout << brand << "汽车加速到 " << speed << " km/h" << endl;
    }
};

class Motorcycle : public Vehicle {
public:
    Motorcycle(string b, int s) : Vehicle(b, s) {}

    void start() override {
        cout << brand << "摩托车启动" << endl;
    }

    void stop() override {
        cout << brand << "摩托车停止" << endl;
        speed = 0;
    }

    void accelerate(int increment) override {
        speed += increment;
        cout << brand << "摩托车加速到 " << speed << " km/h" << endl;
    }
};

int main() {
    Car car("Toyota", 0);
    Motorcycle moto("Honda", 0);

    car.start();
    car.accelerate(50);
    car.displayInfo();
    car.stop();

    cout << "---" << endl;

    moto.start();
    moto.accelerate(80);
    moto.displayInfo();
    moto.stop();

    return 0;
}

实践示例

图形绘制系统

cpp
#include <iostream>
#include <string>
#include <vector>
#include <memory>

using namespace std;

class Drawable {
public:
    virtual void draw() const = 0;
    virtual double getArea() const = 0;
    virtual ~Drawable() = default;
};

class Point {
public:
    double x, y;
    Point(double x = 0, double y = 0) : x(x), y(y) {}
};

class Shape : public Drawable {
protected:
    Point position;
    string color;

public:
    Shape(Point p, string c) : position(p), color(c) {}

    virtual void move(double dx, double dy) {
        position.x += dx;
        position.y += dy;
    }

    Point getPosition() const { return position; }
    string getColor() const { return color; }
    void setColor(const string &c) { color = c; }
};

class Rectangle : public Shape {
private:
    double width, height;

public:
    Rectangle(Point p, double w, double h, string c)
        : Shape(p, c), width(w), height(h) {}

    void draw() const override {
        cout << "绘制矩形: 位置(" << position.x << "," << position.y
             << "), 宽" << width << ", 高" << height
             << ", 颜色" << color << endl;
    }

    double getArea() const override {
        return width * height;
    }

    double getWidth() const { return width; }
    double getHeight() const { return height; }
};

class Circle : public Shape {
private:
    double radius;

public:
    Circle(Point p, double r, string c)
        : Shape(p, c), radius(r) {}

    void draw() const override {
        cout << "绘制圆形: 圆心(" << position.x << "," << position.y
             << "), 半径" << radius
             << ", 颜色" << color << endl;
    }

    double getArea() const override {
        return 3.14159 * radius * radius;
    }

    double getRadius() const { return radius; }
};

class Triangle : public Shape {
private:
    double base, height;

public:
    Triangle(Point p, double b, double h, string c)
        : Shape(p, c), base(b), height(h) {}

    void draw() const override {
        cout << "绘制三角形: 位置(" << position.x << "," << position.y
             << "), 底边" << base << ", 高" << height
             << ", 颜色" << color << endl;
    }

    double getArea() const override {
        return 0.5 * base * height;
    }
};

class Canvas {
private:
    vector<unique_ptr<Shape>> shapes;

public:
    void addShape(unique_ptr<Shape> shape) {
        shapes.push_back(move(shape));
    }

    void drawAll() const {
        cout << "\n=== 画布内容 ===" << endl;
        for (const auto &shape : shapes) {
            shape->draw();
        }
        cout << "================\n" << endl;
    }

    double getTotalArea() const {
        double total = 0;
        for (const auto &shape : shapes) {
            total += shape->getArea();
        }
        return total;
    }

    size_t getShapeCount() const {
        return shapes.size();
    }
};

int main() {
    Canvas canvas;

    canvas.addShape(make_unique<Rectangle>(Point(0, 0), 10, 5, "红色"));
    canvas.addShape(make_unique<Circle>(Point(5, 5), 3, "蓝色"));
    canvas.addShape(make_unique<Triangle>(Point(2, 3), 6, 4, "绿色"));

    canvas.drawAll();

    cout << "图形数量: " << canvas.getShapeCount() << endl;
    cout << "总面积: " << canvas.getTotalArea() << endl;

    return 0;
}

小结

面向对象三大特性:

特性说明
封装隐藏实现细节,提供公共接口
继承代码复用,建立类层次结构
多态同一接口,不同实现

关键概念:

  • 构造函数/析构函数:对象的创建与销毁
  • 访问控制:public、private、protected
  • 虚函数:实现运行时多态
  • 纯虚函数:定义抽象类
  • 运算符重载:自定义类型的运算行为

导航