当前位置: 首页 > news >正文

C++进阶——类与对象

一、基础概念

  1. 什么是类?

定义:类是用户自定义的数据类型,是对象的蓝图或模板。
组成:

成员变量(属性):描述对象的特征(如:汽车的品牌、颜色)
成员函数(方法):定义对象的行为(如:汽车启动、加速)

  1. 什么是对象?

定义:对象是类的实例(Instance),占用内存空间。
类比:

类 → 建筑设计图纸
对象 → 按图纸建造的房子

二、类的定义与使用

  1. 基本语法
class ClassName {
public:     // 访问修饰符(后续详解)
    // 成员变量
    DataType member1;
    DataType member2;

    // 成员函数
    ReturnType method1(Parameters) { ... }
    ReturnType method2(Parameters);
};

// 类外定义成员函数
ReturnType ClassName::method2(Parameters) { ... }
  1. 示例:汽车类
#include <iostream>
#include <string>

class Car {
public:
    // 成员变量
    std::string brand;
    std::string color;
    int speed;

    // 成员函数
    void accelerate(int increment) {
        speed += increment;
    }

    void displayInfo() {
        std::cout << brand << " " << color << ", Speed: " << speed << " km/h\n";
    }
};

int main() {
    // 创建对象
    Car myCar;
    myCar.brand = "Toyota";
    myCar.color = "Red";
    myCar.speed = 0;

    // 调用方法
    myCar.accelerate(20);
    myCar.displayInfo(); // 输出: Toyota Red, Speed: 20 km/h

    return 0;
}

三、访问控制

  1. 访问修饰符
  • public:类外可直接访问
  • private(默认):仅类内和友元可访问
  • protected:类内、派生类、友元可访问
  1. 封装(Encapsulation)原则
    隐藏内部实现,通过公共接口控制访问
  • 目的:规范访问
  • 示例:
class BankAccount {
private:
    double balance; // 私有变量

public:
    void deposit(double amount) {
        if (amount > 0) balance += amount;
    }

    double getBalance() {
        return balance;
    }
};

int main() {
    BankAccount account;
    account.deposit(1000);
    // account.balance = -500; // 错误!无法直接访问私有成员
    std::cout << account.getBalance(); // 正确
}

四、构造函数(Constructor)与析构函数(Destructor)

  1. 构造函数
  • 作用:初始化对象(自动调用)
  • 特点:
    与类同名
    无返回类型
    可重载(多个构造函数)
  • 示例:
class Student {
private:
    std::string name;
    int age;

public:
    // 默认构造函数
    Student() : name("Unknown"), age(0) {}

    // 带参数构造函数
    Student(std::string n, int a) : name(n), age(a) {}

    void display() {
        std::cout << name << ", " << age << " years old\n";
    }
};

int main() {
    Student s1;              // 调用默认构造函数
    Student s2("Alice", 20); // 调用带参数构造函数
    s2.display(); // Alice, 20 years old
}
  1. 析构函数
  • 作用:清理资源(如释放内存)
  • 特点:
    名称:~ClassName()
    无参数,不可重载
  • 示例:
class FileHandler {
public:
    FileHandler() { std::cout << "File opened\n"; }
    ~FileHandler() { std::cout << "File closed\n"; } // 析构函数
};

int main() {
    FileHandler f; // 构造时输出
    // 析构函数在对象离开作用域时自动调用
}
// 输出:
// File opened
// File closed

五、静态成员

  1. 静态变量
  • 特性:
    属于类而非对象
    所有对象共享同一份拷贝
  • 示例:
class Counter {
public:
    static int count; // 声明静态变量

    Counter() { count++; }
    ~Counter() { count--; }
};

int Counter::count = 0; // 定义并初始化

int main() {
    Counter c1, c2;//定义c1和c2时都进行了加一操作
    std::cout << Counter::count; // 输出 2
}
  1. 静态函数
  • 只能访问静态成员
  • 示例:
class MathUtils {
public:
    static int square(int x) { return x * x; }
};

int main() {
    std::cout << MathUtils::square(5); // 输出 25
}

六、继承(Inheritance)

  1. 基本语法
class BaseClass { /* ... */ };

// 公有继承
class DerivedClass : public BaseClass { /* ... */ };
  1. 示例:动物类层次
class Animal {
public:
    void eat() { std::cout << "Eating...\n"; }
};

class Dog : public Animal {
public:
    void bark() { std::cout << "Woof!\n"; }
};

int main() {
    Dog myDog;
    myDog.eat();  // 继承自基类
    myDog.bark(); // 派生类自有方法
}

七、多态(Polymorphism)

  1. 虚函数(Virtual Functions)
class Shape {
public:
    virtual void draw() { // 虚函数
        std::cout << "Drawing a shape\n";
    }
};

class Circle : public Shape {
public:
    void draw() override { // 重写虚函数
        std::cout << "Drawing a circle\n";
    }
};

int main() {
    Shape* shape = new Circle();
    shape->draw(); // 输出: Drawing a circle
    delete shape;
}

八、练习与巩固

基础练习:

定义一个 Book 类,包含书名、作者、价格属性和显示信息的方法。

  • 简单版本代码示例:
#include <iostream>
#include <string>

class Book {
public:
    // 成员变量
    std::string book_name;
    std::string author;
    float price;

    // 成员函数

    void displayInfo() {
        std::cout << book_name << " " << author << ", price: " << price << "yuan\n";
    }
};

int main() {
    // 创建对象
    Book mybook;
    mybook.book_name = "if give me three days light";
    mybook.author = "omb";
    mybook.price = 20.5;

    // 调用方法
    mybook.displayInfo(); // 输出: Toyota Red, Speed: 20 km/h

    return 0;
}
  • 改进版:

代码评价与改进建议

  1. 封装性不足

问题:成员变量(book_name, author, price)被声明为 public,外部可以直接修改,破坏了面向对象的封装原则。
改进:将成员变量设为 private,通过公共方法(getter/setter)访问。

  1. 缺少构造函数

问题:对象创建后需要逐个手动赋值,容易遗漏初始化。
改进:添加构造函数,方便对象初始化。

  1. 代码规范性

建议:避免 using namespace std;,改为显式使用 std:: 前缀(防止命名冲突)。

改进后的代码:

#include <iostream>
#include <string>

class Book {
private:  // 成员变量设为私有,增强封装性
    std::string book_name;
    std::string author;
    double price;  // 使用 double 提高精度

public:
    // 构造函数(初始化成员变量)
    Book(const std::string& name, const std::string& author_name, double book_price)
        : book_name(name), author(author_name), price(book_price) {}

    // 显示书籍信息(const 表示不修改成员变量)
    void displayInfo() const {
        std::cout << "Book: " << book_name 
                  << "\nAuthor: " << author 
                  << "\nPrice: " << price << " yuan\n";
    }

    // Getter/Setter 方法(保护数据安全)
    void setPrice(double new_price) {
        if (new_price >= 0) {  // 简单的数据校验
            price = new_price;
        }
    }

    double getPrice() const { return price; }
    // 可以类似添加其他属性的 getter/setter
};

int main() {
    // 使用构造函数初始化对象
    Book mybook("If I Had Three Days of Light", "Helen Keller", 20.5);

    // 调用方法显示信息
    mybook.displayInfo();  // 输出正确的书籍信息

    // 修改价格(通过 setter)
    mybook.setPrice(25.0);
    std::cout << "Updated price: " << mybook.getPrice() << " yuan\n";

    return 0;
}

改进点详解

  1. 封装性

为什么重要:封装是面向对象的核心原则,可以防止外部代码意外修改对象内部状态。
实现方式:

成员变量设为 private
通过 getPrice() 和 setPrice() 方法访问和修改价格

  1. 构造函数

优势:

  • 强制在创建对象时提供完整初始化数据
  • 避免对象处于“半初始化”状态
  • 使用成员初始化列表(更高效)
    语法:
Book(const std::string& name, const std::string& author_name, double book_price)
    : book_name(name), author(author_name), price(book_price) {}
  1. 输出格式修正

修正后的输出示例:

Book: If I Had Three Days of LightAuthor: Helen KellerPrice: 20.5 yuan

  1. 其他优化

数据类型:price 改为 double(更精确的浮点数)
const 正确性:displayInfo() 和 getPrice() 标记为 const
数据校验:在 setPrice() 中检查价格非负

进阶挑战:

  • 实现一个 Stack 类,包含压栈(push)、弹栈(pop)、查看栈顶元素的方法
  • 使用私有数组存储数据,确保封装性

相关文章:

  • 基于物理信息强化学习的非线性系统最优控制
  • Java面试黄金宝典10
  • CSRF SSRF RCE
  • Django 生产环境静态文件处理
  • 代码随想录算法训练营第十四天(2)|151.翻转字符串里的单词
  • Python Cookbook-4.9 从字典中取值
  • 探索 Ollama:开源大语言模型平台的无限可能​
  • 《大话数据结构》学习记录----第三章线性表
  • SPI 机制与 Spring Boot AutoConfiguration 对比解析
  • 基于linux平台的C语言入门教程(7)类型转换
  • 计算机网络高频(二)TCP/IP基础
  • 【HarmonyOS Next之旅】DevEco Studio使用指南(六)
  • MQTT的安装和使用
  • Leetcode—15. 三数之和(哈希表—基础算法)
  • 【JAVA进阶篇教学】第十一篇:Java中ReentrantLock锁讲解
  • 基于Spring Boot的停车场管理系统的设计与实现(LW+源码+讲解)
  • 在 macOS 上配置 SSH 连接 GitHub
  • 希尔排序
  • C++脚本化方案调研
  • Axure PR 9.0(发音:Ack-sure)原型图工具入门教程:链接交互
  • 万里云端遇见上博--搭乘“上博号”主题飞机体验记
  • 李云泽:房地产“白名单”贷款审批通过金额增至6.7万亿元
  • “模”范生上海,如何再进阶?
  • 山大齐鲁医院通报“子宫肌瘤论文现男性患者”:存在学术不端
  • 媒体:南京秦淮区卫健委回应一医院涉嫌违规提供试管婴儿服务
  • 特朗普要征100%关税,好莱坞这批境外摄制新片有麻烦了