shiyb
2025-05-19 9ca199497985c526c31e8884f6911fd49be6b807
Merge branch 'master' of ssh://117.78.1.188:29418/test-upload
修改了错误示例
1个文件已删除
3个文件已修改
287 ■■■■ 已修改文件
Test/Test.pro 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Test/errorexample.cpp 267 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Test/errorexample.h 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Test/linestyle.cpp 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Test/Test.pro
@@ -17,13 +17,11 @@
SOURCES += \
    errorexample.cpp \
    linestyle.cpp \
    main.cpp \
    mainwindow.cpp
HEADERS += \
    errorexample.h \
    linestyle.h \
    mainwindow.h
FORMS += \
Test/errorexample.cpp
@@ -1,105 +1,228 @@
#include "errorexample.h"
#include <QFile>
#include <QLabel>
#include <QPushButton>
errorexample::errorexample() {
  // 1.未包含必要的头文件
  // 错误:缺少 #include <QLabel>
  QLabel label("Hello");  // 编译错误:'QLabel' was not declared in this scope
  label.show();
  // 2.未初始化指针
  QLabel *label4;
  label4->setText("Hello");  // 错误:使用未初始化的指针
  //-----------指针常见问题---------------
  // 修复:初始化指针
  QLabel *label5 = new QLabel;
  //①空指针解引用
  QWidget *widget = nullptr;
  widget->show();  //对值为nullptr的指针进行访问操作,会引发崩溃
  // 3.父对象管理不当导致内存泄露
  QLabel *label1 = new QLabel("Memory Leak");
  label1->show();
  //解决办法:
  QWidget *widget1 = nullptr;
  if (widget1) {  //使用指针前,先确认其是否为nullptr
    widget1->show();
  }
  // 正确做法:设置父对象,Qt会自动管理内存
  //②野指针
  //指针所指向的内存已经被释放,但后续仍在使用该指针
  QWidget *widget2 = new QWidget;
  delete widget2;
  widget2->show();  //此时widget2已经变成野指针
  //解决办法:
  //对象释放之后,及时将指针置为nullptr(利用 Qt
  //对象的父子关系机制来自动管理内存)
  QWidget *widget3 = new QWidget;
  delete widget3;
  widget3 = nullptr;  //避免野指针
  //③内存泄露:未释放动态分配的内存
  void createLeak() {
    int *ptr = new int(10);  //分配后未释放
  }
  //解决办法:
  void createLeak() {
    int *ptr = new int(10);  //分配后未释放
    delete ptr;
    ptr = nullptr;
  }
  //④父子关系误用
  QWidget *parent = new QWidget;
  QLabel *managedLabel = new QLabel("Managed", parent);
  QPushButton *button = new QPushButton(parent);
  delete button;  // 手动删除子对象
  delete parent;  // 崩溃!父对象试图再次删除已释放的 button
  // 4.使用已删除的对象
  QLabel *label2 = new QLabel("Delete Me");
  delete label2;
  //解决办法:依赖对象树自动管理
  QWidget *parent2 = new QWidget;
  QPushButton *button2 = new QPushButton(parent);
  delete parent2;  // 自动删除所有子对象(包括 button)
  // 错误:访问已删除的对象
  label2->setText("Oops");  // 未定义行为
  //⑤智能指针与对象树冲突
  //混合使用父对象和智能指针
  QWidget *parent3 = new QWidget;
  // 错误:父对象已管理 button,智能指针会导致双重释放
  std::unique_ptr<QPushButton> button3(new QPushButton(parent));
  // 5.字符串编码问题
  QLabel *label3 = new QLabel;
  // 错误:硬编码非ASCII字符串
  label3->setText("中文文本");  // 可能显示乱码,取决于源文件编码
  //解决办法1:仅用父对象管理
  QWidget *parent4 = new QWidget;
  QPushButton *button4 = new QPushButton(parent4);  // 父对象负责释放
  // 正确做法:使用tr()进行翻译
  label3->setText(tr("中文文本"));
  //解决办法2:无父对象时使用智能指针
  std::unique_ptr<QPushButton> button5 = std::make_unique<QPushButton>();
  // 6.容器越界访问
  QList<int> list = {1, 2, 3};
  // 错误:越界访问
  int value = list[3];  // 索引最大为2
  // 正确做法:使用at()并检查边界
  if (list.size() > 3) {
    int safeValue = list.at(3);  // at()会在越界时抛出异常
  //⑥容器中的指针管理
  // 忘记释放files数组及其中的指针所指向的内存
  QFile *files = new QFile[10];
  for (int i = 0; i < 10; ++i) {
    files[i].setFileName("file" + QString::number(i));
  }
  // 7.缺失终止条件的For循环
  for (int i = 0;; i++) {  // 错误:无终止条件
                           //循环体
  //解决办法:
  QFile **files1 = new QFile *[10];
  for (int i = 0; i < 10; ++i) {
    files[i].setFileName("file" + QString::number(i));
  }
  for (int i = 0; i < 10; ++i) {
    delete files1[i];
  }
  delete[] files;
  //-----------常见逻辑错误---------------
  //①无限循环
  //错误:(无终止条件)
  for (int i = 0; i < 10;) {
    qDebug() << "Looping...";
    // 忘记写i++
  }
  // 正确写法:
  for (int i = 0; i < 10; i++) {  // 添加终止条件
                                  //循环体
  //错误:死循环(条件恒为真)
  while (true) {
    //代码块          未提供退出机制
  }
  // 8.误用 = 代替 ==
  if (x = 5) {  // 误将赋值操作当作比较,条件始终为 true(除非 x 是布尔类型)
                // ...
  //解决办法
  // 增加i++
  for (int i = 0; i < 10; i++) {
    qDebug() << "Looping..." << i;
  }
  // 9.事件处理未调用基类实现
  void CustomWidget::paintEvent(QPaintEvent * event) {
    // 错误:未调用基类实现
    QPainter painter(this);
    // 缺少:QWidget::paintEvent(event);
  //使用break或return退出循环
  while (true) {
    if (data.isEmpty()) break;  // 条件满足时退出
  }
  // 10.信号槽参数不匹配
  // 错误:信号参数与槽参数类型不匹配
  connect(sender, &Sender::valueChanged(int), receiver,
          &Receiver::updateValue(QString));
  //②数据/容器越界访问
  // 错误:访问越界(索引0~9,但循环到i=10)
  QVector<int> numbers(10);
  for (int i = 0; i <= 10; ++i) {  // ӦΪi < 10
    numbers[i] = i;                // i=10时越界
    // 错误:使用空容器
    QStringList names;
    qDebug() << names[0];  // 访问空容器的第一个元素
  // 修复:确保参数类型一致
  connect(sender, &Sender::valueChanged(int), receiver,
          &Receiver::updateValue(int));
    //解决办法
    //使用安全的访问方法(如at()代替[])
    qDebug() << numbers.at(10);
    //检查容器是否为空
    if (!names.isEmpty()) {
      qDebug() << names[0];
    }
  // 11.未实现纯虚函数
  class MyInterface {
   public:
    virtual void pureVirtual() = 0;
  };
    // 2.未初始化指针
    QLabel *label4;
    label4->setText("Hello");  // 错误:使用未初始化的指针
  class MyClass : public MyInterface {
    // 错误:未实现纯虚函数
  };
    // 修复:初始化指针
    QLabel *label5 = new QLabel;
  // 修复:实现纯虚函数
  void MyClass::pureVirtual() { /* 实现 */
    // 3.父对象管理不当导致内存泄露
    QLabel *label1 = new QLabel("Memory Leak");
    label1->show();
    // 正确做法:设置父对象,Qt会自动管理内存
    QWidget *parent = new QWidget;
    QLabel *managedLabel = new QLabel("Managed", parent);
    // 4.使用已删除的对象
    QLabel *label2 = new QLabel("Delete Me");
    delete label2;
    // 错误:访问已删除的对象
    label2->setText("Oops");  // 未定义行为
    // 5.字符串编码问题
    QLabel *label3 = new QLabel;
    // 错误:硬编码非ASCII字符串
    label3->setText("中文文本");  // 可能显示乱码,取决于源文件编码
    // 正确做法:使用tr()进行翻译
    label3->setText(tr("中文文本"));
    // 6.容器越界访问
    QList<int> list = {1, 2, 3};
    // 错误:越界访问
    int value = list[3];  // 索引最大为2
    // 正确做法:使用at()并检查边界
    if (list.size() > 3) {
      int safeValue = list.at(3);  // at()会在越界时抛出异常
    }
    // 7.缺失终止条件的For循环
    for (int i = 0;; i++) {  // 错误:无终止条件
                             //循环体
    }
    // 正确写法:
    for (int i = 0; i < 10; i++) {  // 添加终止条件
                                    //循环体
    }
    // 8.误用 = 代替 ==
    if (x = 5) {  // 误将赋值操作当作比较,条件始终为 true(除非 x 是布尔类型)
                  // ...
    }
    // 9.事件处理未调用基类实现
    void CustomWidget::paintEvent(QPaintEvent * event) {
      // 错误:未调用基类实现
      QPainter painter(this);
      // 缺少:QWidget::paintEvent(event);
    }
    // 10.信号槽参数不匹配
    // 错误:信号参数与槽参数类型不匹配
    connect(sender, &Sender::valueChanged(int), receiver,
            &Receiver::updateValue(QString));
    // 修复:确保参数类型一致
    connect(sender, &Sender::valueChanged(int), receiver,
            &Receiver::updateValue(int));
    // 11.未实现纯虚函数
    class MyInterface {
     public:
      virtual void pureVirtual() = 0;
    };
    class MyClass : public MyInterface {
      // 错误:未实现纯虚函数
    };
    // 修复:实现纯虚函数
    void MyClass::pureVirtual() { /* 实现 */
    }
    // 12.未正确实现拷贝构造函数
    class MyClass1 {
     public:
      QWidget *widget;
      MyClass1(const MyClass1 &other) {
        widget = other.widget;
      }  // 错误:浅拷贝
    };
    // 修复:深拷贝或禁用拷贝构造函数
    MyClass1(const MyClass1 &other) = delete;
  }
  // 12.未正确实现拷贝构造函数
  class MyClass1 {
   public:
    QWidget *widget;
    MyClass1(const MyClass1 &other) { widget = other.widget; }  // 错误:浅拷贝
  };
  // 修复:深拷贝或禁用拷贝构造函数
  MyClass1(const MyClass1 &other) = delete;
}
Test/errorexample.h
@@ -3,11 +3,11 @@
#include <QObject>
class errorexample
{
    Q_OBJECT
public:
    errorexample();
class errorexample {
  Q_OBJECT
 public:
  errorexample();
  void createLeak();
};
#endif // ERROREXAMPLE_H
#endif  // ERROREXAMPLE_H
Test/linestyle.cpp
File was deleted