• C++对象与对象的关系


    目录

    依赖

    关联

    关联与聚合

    组合

    对应的类型设计: 

    类型的组合:

    在一个系统中,一个对象可能与不同的对象相关,以下是不同的关系:

    • 依赖(Dependency)(使用一个)
    • 关联(Association)(使用一个)
    • 聚合(Aggregation)(有一个,有整体和部分的关系)
    • 组合(Composition)(有一个,“用...来实现”,“用...来构成”,有整体和部分的关系)
    • 继承(Inheritance)(是一个)
    • 类模板(Class template)

    依赖

    程序类之间的“依赖”关系主要体现出的是一种使用关系,对于两个相对独立的对象, 当一个对象负 责构造另一个对象的实例,或者当一个对象依赖于另一个对象所提供的服务时,这两个对象之间主要体现为依赖关系。

    在类型的设计中,依赖关系主要体现在目标类型的对象(实例),作为当前类型方法的局部对象或 者方法的参数类型。

    1. class Book{}; // 书籍
    2. class Food{}; // 食物
    3. class Human // 人类
    4. {
    5. public:
    6. void Read(Book book);
    7. void Eat(Food food);
    8. };
    9. ///
    10. class Notebook_computer //笔记本计算机
    11. {
    12. };
    13. class desktop_computer //台式计算机
    14. {
    15. private:
    16. string cup;
    17. int Memory;
    18. int ssdist; //Solid state disk
    19. };
    20. class Student
    21. {
    22. public:
    23. void Study_Programming(Notebook_computer compute); //学习编程
    24. void Study_Programming(desktop_computer compute);
    25. void Study_Programming(Book book); //
    26. };

    关联

    对于两个相互独立的对象,当对象A与另一个对象B存在固定的对应关系时,这两个对象之间为关 联关系。关联关系是依赖关系的特例。

    在类型的设计中,关联关系主要体现在目标类型的指针或引用,作为当前类型的属性成员。没有整 体和部分的关系,只是有关系而已。

    1. class Book{}; // 书籍
    2. class Person
    3. {
    4. private:
    5. Book *ptr;// 弱关联
    6. public:
    7. Person():ptr(nullptr) {}
    8. Person(Book *p):ptr(p) {}
    9. ~Person() {}
    10. void SetBook(Book *p) { ptr = p;}
    11. void Study()
    12. {
    13. if(Ptr != nullptr)
    14. {
    15. cout<<"看一会书 ... "<
    16. }else
    17. {
    18. cout<<"没有书可以看 ... "<
    19. }
    20. }
    21. };
    22. // 人对象与书籍对象没有整体和部分的关系,只是有关系而已。
    23. class Student
    24. {
    25. Book &_book ;// 强关联
    26. public:
    27. Student() {} // error;
    28. Student(Book bk):_book(bk) {} // error;
    29. Student(Book &book):_book(book){} // ok;
    30. Student() {}
    31. };
    32. // 学生对象与书籍对象没有整体和部分的关系,只是有关系而已
    33. class Dog;
    34. class Master // 狗主
    35. {
    36. Dog *pdog;
    37. public:
    38. };
    39. class Dog
    40. {
    41. Mastrer *pm;
    42. };
    43. // 主人对象与狗对象没有整体和部分的关系,只是有关系而已。

    如果Employee类所代表的物理事物与TimeCard类所代表的物理事物存在组成或者构成关系,则此 时的关联就演变为聚合(松散的包含)或者组合(较强的构成)关系。

    关联与聚合

    在概念上,它们都是对象实例间的一种静态关系,都是在类的抽象层次上的定义,并且最终都可以通过对象的属性来体现。但它们差别是,聚合关系所涉及的两个类型的对象,在现实世界中的含义有明显的has - a (有一个)的语义,能够区分哪个是整体,哪个是部分,而关联所涉及的对象之间没有这种语义,即分不出整体和部分的关系。用...来组成。

    1. class Point // 点
    2. {
    3. private:
    4. float _x;
    5. float _y;
    6. public:
    7. Point():_x(0.0),_y(0.0) {}
    8. Point(float x,float y):_x(x),_y(y) {}
    9. Point(const Point &p):_x(p._x),_y(p._y) // 按位拷贝 inline 函数
    10. {}
    11. Point & operator=(const Point &p) // 按位赋值 inline 函数
    12. {
    13. if(this != &p)
    14. {
    15. _x = p._x;
    16. _y = p._y;
    17. }
    18. return *this;
    19. }
    20. ~Point() {}
    21. float & pointX() { return _x;}
    22. const float & pointX() const { return _x;}
    23. float & pointY() { return _y;}
    24. const float & pointY() const { return _y;}
    25. };
    26. class Circle
    27. {
    28. private:
    29. Point _center; // 圆心
    30. float _radius; // 半径
    31. };
    32. //此时整体与部分之间是可分离的,它们可以具有各自的生命周期,
    33. //部分可以属于多个整体对象,也可以为多个整体对象共享。
    34. class Circle
    35. {
    36. private:
    37. Point *pCenter;
    38. float _radius;
    39. };

    组合

    当对象A是对象B的属性时,称对象B包含对象A。意味着 "用...来实现,用...来构造"

    相比于聚合,组合是一种耦合度更强的关联关系。存在组合关系的类表示“整体-部分”的关联关系,“整 体”负责“部分”的生命周期,他们之间是共生共死的;并且“部分”单独存在时没有任何意义。

    在下图的例子中,People与Soul、Body之间是组合关系,当人的生命周期开始时,必须同时有灵 魂和肉体;当人的生命周期结束时,灵魂肉体随之消亡;无论是灵魂还是肉体,都不能单独存在,他们 必须作为人的组成部分存在。

    对应的类型设计: 

    一个类中包含了另一个类的对象作为属性成员,即在类中含有类类型的数据成员 。

    1. class Soul{};
    2. class Body{};
    3. class People
    4. {
    5. Soul _soul;
    6. Body _body;
    7. //组合关系中的成员变量一般会在构造方法中赋值
    8. public:
    9. People(Soul soul, Body body):_soul(soul),_body(_body)
    10. {
    11. }
    12. public:
    13. void study(){
    14. cout<<" 学习要用灵魂"<getName()<
    15. }
    16. void eat(){
    17. cout<<"吃饭用身体:"<getName()<
    18. }
    19. };

    类型的组合:

    对象线段是用两个点对象来实现:点与线的组合

    示例:

    1. class Point // 点
    2. {
    3. private:
    4. float _x;
    5. float _y;
    6. protected:
    7. Point():_x(0.0),_y(0.0) {}
    8. Point(float x,float y):_x(x),_y(y) {}
    9. Point(const Point &) = default; // 按位拷贝 inline 函数
    10. public:
    11. Point & operator=(const Point &) = default; // 按位赋值 inline 函数
    12. ~Point() {}
    13. float & pointX() { return _x;}
    14. const float & pointX() const { return _x;}
    15. float & pointY() { return _y;}
    16. const float & pointY() const { return _y;}
    17. };
    18. class Line // 线
    19. {
    20. private:
    21. Point _start;
    22. Point _end;
    23. float _length;
    24. float distance()
    25. {
    26. float xd = _start.pointX() - _end.pointX();
    27. float yd = _start.pointY() - _end.pointY();
    28. _length = sqrt(xd*dx + yd*yd);
    29. }
    30. public:
    31. Line():_length(0) {}
    32. Line(const Point &a,const Point &b):_start(a),_end(b)
    33. {
    34. distance();
    35. }
    36. Line(const Line &) = default;
    37. Line & operator=(const Line &) = default;
    38. ~Line() {}
    39. float length() const
    40. {
    41. return _length;
    42. }
    43. const Point & get_Start()const { return _start;}
    44. const Point & get_End() const { return _end;}
    45. void set_Start(const Point &a)
    46. {
    47. _start = s;
    48. distance();
    49. }
    50. void set_End(const Point &b)
    51. {
    52. _end = b;
    53. distance();
    54. }
    55. };
    56. int main()
    57. {
    58. Point a(1,2),b(5,5);
    59. Line s(a,b);
    60. cout<length()<
    61. return 0;
    62. }

    发一个可应用于多个软件的文件加密模块,该模块可以对文件中的数据进行加密并将加密之后的数 据存储在一个新文件中,具体的流程包括三个部分,分别是读取源文件、加密、保存加密之后的文件, 其中,读取文件和保存文件使用流来实现,加密操作通过求模运算实现。这三个操作相对独立,为了实 现代码的独立重用,让设计更符合单一职责原则,这三个操作的业务代码封装在三个不同的类中。

    现使用外观模式设计该文件加密模块。

    1. class ReaderFile
    2. {
    3. public:
    4. string Read(const string& filename)
    5. {
    6. cout << "读取文件,获取明文:";
    7. ifstream ifile;
    8. char ch;
    9. std::string src;
    10. ifile.open(filename, ios::in);
    11. if (!ifile.is_open())
    12. {
    13. cout << "文件不存在!" << endl;
    14. return src;
    15. }
    16. while (!ifile.eof())
    17. {
    18. ifile.get(ch);
    19. src.push_back(ch); // src+=ch;
    20. }
    21. cout << src << endl;
    22. ifile.close();
    23. return src;
    24. }
    25. };
    26. class Encryptor //加密器 CipherMachine // 密码机
    27. {
    28. public:
    29. string Encrypt(const string& plaintext)
    30. {
    31. cout << "数据加密,将明文转换为密文:";
    32. std::string es;
    33. for (auto& x : plaintext)
    34. {
    35. char c = x;
    36. if (isalpha(c))
    37. {
    38. c = ((c + 5) % 26 + 'a');
    39. }
    40. es += c;
    41. }
    42. cout << es << endl;
    43. return es;
    44. }
    45. };
    46. class WriterFile
    47. {
    48. public:
    49. void Write(const string& filename, const string& ciphertext)
    50. {
    51. cout << "保存密文,写入文件。" << endl;
    52. ofstream ofile;
    53. ofile.open(filename);
    54. if (!ofile.is_open())
    55. {
    56. cout << "文件不存在" << endl;
    57. return;
    58. }
    59. for (auto& x : ciphertext)
    60. {
    61. ofile.put(x);
    62. }
    63. ofile.close();
    64. return;
    65. }
    66. };
    67. // EncryptFacade.cs
    68. class EncryptFacade
    69. {
    70. //维持对其他对象的引用
    71. private:
    72. ReaderFile reader;
    73. Encryptor encrypt;
    74. WriterFile writer;
    75. public:
    76. EncryptFacade() {}
    77. //调用其他对象的业务方法
    78. void FileEncrypt(string fileNameSrc, string fileNameDes)
    79. {
    80. string plainStr = reader.Read(fileNameSrc);
    81. string encryptStr = encrypt.Encrypt(plainStr);
    82. writer.Write(fileNameDes, encryptStr);
    83. }
    84. };
    85. int main()
    86. {
    87. EncryptFacade ef;
    88. ef.FileEncrypt("src.txt", "des.txt");
    89. return 0;
    90. }
  • 相关阅读:
    【Tomcat】Tomcat 运行原理
    K-近邻算法分类和回归
    实现分布式锁SchedulerLock
    T02 ExtractSubject 项目开发总结
    vue通过span-method合并列之后,合并列显示在中间位置,根据鼠标滑动跟随展示
    DxO PureRAW:赋予RAW图像生命,打造非凡视觉体验 mac/win版
    1.初识jQuery
    linux软硬连接
    《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(17)-Fiddler如何充当第三者,再识AutoResponder标签-下篇
    react d3使用循环显示多个地图
  • 原文地址:https://blog.csdn.net/weixin_59179454/article/details/127796350