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

条款28:避免返回 handles 指向对象的内部成分

 创建一个矩形的类(Rectangle),为保持Rectangle对象较小,可以只在其对象中保存一个指针,用于指向辅助的结构体,定义其范围的点数据存放在辅助的结构体中:

class Point { // 表示点的类
public:Point(int x, int y);...void setX(int newVal);void setY(int newVal);...
};
struct RectData { // 矩形的点数据Point ulhc; // ulhc = " upper left-hand corner"Point lrhc; // lrhc = " lower right-hand corner"
};
class Rectangle {...Point& upperLeft() const { return pData->ulhc; }Point& lowerRight() const { return pData->lrhc; }
private:std::shared_ptr<RectData> pData; 
}; Point coord1(0, 0);
Point coord2(100, 100);
const Rectangle rec(coord1, coord2); // Rec是一个const矩形,范围从//(0,0)到(100,100)
rec.upperLeft().setX(50); // 现在变为 (50, 0) 到 (100, 100)!

 这个设计可以编译,但它是错误的。我们设计的类返回的是一个const修饰的对象,但是我们还是可以修改内部对象的值。
我们可以为函数的返回类型添加const限制来解决这个问题:

class Rectangle {
public:...const Point& upperLeft() const { return pData->ulhc; }const Point& lowerRight() const { return pData->lrhc; }...
};

 即便如此,upperLeft和lowerRight仍然会返回对象内部的句柄,这在其他方面可能会造成问题。特别是,它可能导致悬空(dangling )句柄:指向不再存在的对象的句柄。

#include <iostream>
#include <string>
class Point { // 表示点的类
public:Point() {};Point(int x, int y) :_x{x},_y{y}{}void setX(int newVal) {_x = newVal;}void setY(int newVal) {_y = newVal;}std::string toString() const {std::string result = "(x:" + std::to_string(_x) + "," + std::to_string(_y) + ")";return result;}
private:int _x = 0;int _y = 0;
};
struct RectData { // 矩形的点数据Point ulhc; // ulhc = " upper left-hand corner"Point lrhc; // lrhc = " lower right-hand corner"
};
class Rectangle {
public:Rectangle(){}Rectangle(const Point& p1, const Point& p2) {RectData rectData;rectData.ulhc = p1;rectData.lrhc = p2;pData = std::make_shared<RectData>(rectData);}~Rectangle(){std::cout << "Rectangle析构函数执行" << std::endl;}const Point& upperLeft() const { return pData->ulhc; }const Point& lowerRight() const { return pData->lrhc; }void print() const{std::cout<<pData->ulhc.toString()<<std::endl;std::cout << pData->lrhc.toString() << std::endl;}
private:std::shared_ptr<RectData> pData;
};Rectangle boudingBox()
{Point coord1(0, 0);Point coord2(100, 100);Rectangle rect(coord1, coord2);return rect;
}int main()
{//Point coord1(0, 0);//Point coord2(100, 100);//const Rectangle rec(coord1, coord2);	//rec.print();//Point right = rec.lowerRight();//std::cout << "+++++++" << right.toString() << std::endl;rec.upperLeft().setX(50); //rec.print();const Point *right = &(boudingBox().lowerRight());std::cout << "+++++++" << right->toString() << std::endl;return 0;
}

在这里插入图片描述
 避免返回指向对象内部的句柄(引用、指针或迭代器)。遵守这个原则将会增加了封装性,帮助const成员函数保持const行为,并可以尽量避免发生悬空句柄的创建。

http://www.lryc.cn/news/285111.html

相关文章:

  • 【人工智能】之深入理解 AI Agent:超越代码的智能助手(2)
  • 如何将一个字符串转换为整数?
  • 【鸿蒙4.0】harmonyos Day 04
  • 微调(fine-tuning)
  • Find My卡片正成为消费电子香饽饽,伦茨科技ST17H6x可以帮到您
  • Es bulk批量导入数据(1w+以上)
  • #laravel 通过手动安装依赖PHPExcel#
  • Webpack 基本使用 - 1
  • 要编译Android 12系统的开机Logo,你需要执行以下步骤:
  • 【JS逆向学习】36kr登陆逆向案例(webpack)
  • R语言的ggplot2绘制分组折线图?
  • [C#]winform部署官方yolov8-obb旋转框检测的onnx模型
  • Git中config配置
  • Java开发安全之:Unreleased Resource: Streams需确保流得到释放
  • 【C++】文件操作
  • 高效能方法 - 任务清单优先级
  • go 语言爬虫库goquery介绍
  • 解决 Navicat 在笔记本外接显示器分辨率自适应展示问题
  • 网络安全产品之认识入侵检测系统
  • 牛客周赛 Round 10 解题报告 | 珂学家 | 三分模板 + 计数DFS + 回文中心扩展
  • SpringBoot 更新业务场景下,如何区分null是清空属性值 还是null为vo属性默认值?
  • 【深度学习每日小知识】NLP 自然语言处理
  • 一文理解Python选择语句
  • MyBatis XML 映射文件中的 SQL 语句可以分为动态语句和静态语句
  • Flask用于生产环境
  • 程序员如何向上管理,升职加薪
  • Microsoft Word 删除空行
  • 基于一次应用卡死问题所做的前端性能评估与优化尝试
  • JVM(上)
  • 【js】js 异步机制详解 Generator / Async / Promise