假设要编写一个小区养狗管理程序,该程序需要一个“主人”类,还需要一个“狗”类。狗是有主人的,主人也有狗。假定狗只有一个主人,但一个主人可以有最多10条狗。该如何处理“主人”类和“狗”类的关系呢?下面是一种直观的写法:

#include<iostream>
using namespace std;
class CDog;
class CMaster
{
CDog dogs[10];
int dog_num;
};
class CDog
{
CMaster m;
};
int main()
{
}

  这种写法是无法通过编译的。因为尽管提前对CDog类进行了声明,但编译到第4行时,编译器还是不知道CDog类的对象是什么样的,所以无法编译定义dog对象的语句。而且这种“人中有狗,狗中有人”的做法导致了循环定义。避免循环定义的方法是在一个类中使用另一个类的指针,而不是对象作为成员变量。例如:

#include<iostream>
using namespace std;
class CDog;
class CMaster
{
CDog* dogs[10];
int dog_num;
};
class CDog
{
CMaster m;
};
int main()
{
}

  上面这种写法在第4行定义了一个CDog类的指针数组在为CMaster类的成员对象。指针就是地址,所以编译器编译到此时不需要知道CDog类是什么样子。这种写法的思想是:当一个CMaster对象养了一条狗时,就有new运算符动态分配一个CDog类的对象,然后在dogs数组中找一个元素,让它指向动态分配的CDog对象。

  这种写法还是不够好。问题出在CDog对象中包含了CMaster对象。在多条狗的主人相同的情况下,多个CDog对象中的CMaster对象都代表同一个主人,这造成了没有必要的冗余——一个主人用一个CMaster对象表示足矣,没有必要对应于多个CMaster对象。而且,在一对多的情况下,当主人的个人信息发生变化时,就需要将与其对应的、位于多个CDog对象中的CMaster成员变量m都找出来修改,这毫无必要,而且麻烦。

  正确写法:

#include<iostream>
using namespace std;
class CMaster;
class CDog
{
CMaster* pm;
};
class CMaster
{
CDog dogs[10];
int dog_num;
};
int main()
{
}

  这样,主人相同的多个CDog对象,其pm指针都指向同一个CMaster对象。实际上,一个主人未必都养10条狗,因此处于节省空间的目的,在CMaster类中设置CDog类对象的指针数组,而不是对象数组,也是一种写法

新标准c++程序设计

正确处理类的复合关系------新标准c++程序设计的更多相关文章

  1. 类与类之间的两种关系------新标准c++程序设计

    在c++中,类和类之间有两种基本关系:复合关系和继承关系. 复合关系也称为“has a”关系或“有”的关系,表现为封闭类,即一个类以另一个类的对象作为成员变量. 继承关系也称为“is a”关系或“是” ...

  2. 类的互相包含------新标准c++程序设计

    #include<iostream> using namespace std; class A; class B{ public: void f(A* pt){}; } class A{ ...

  3. 多态实现的原理------新标准c++程序设计

    “多态”的关键在于通过基类指针或引用调用一个虚函数时,编译时不确定到底调用的是基类还是派生类的函数,运行时才确定.例子: #include<iostream> using namespac ...

  4. 封闭类------新标准c++程序设计

      封闭类:  一个类的成员变量如果是另一个类的对象,就称之为“成员对象”.包含成员对象的类叫封闭类. #include<iostream> using namespace std; cl ...

  5. string类------新标准c++程序设计

    定义: string类是STL中basic_string模板实例化得到的模板类.其定义如下: typedef basic_string<char>string; 构造函数: string类 ...

  6. this指针------新标准c++程序设计

    背景:   c++是在c语言的基础上发展而来的,第一个c++的编译器实际上是将c++程序翻译成c语言程序,然后再用c语言编译器进行编译.c语言没有类的概念,只有结构,函数都是全局函数,没有成员函数.翻 ...

  7. 在成员函数中调用虚函数(关于多态的注意事项)------新标准c++程序设计

    类的成员函数之间可以互相调用.在成员函数(静态成员函数.构造函数和析构函数除外)中调用其他虚成员函数的语句是多态的.例如: #include<iostream> using namespa ...

  8. 多态的作用-游戏编程展示------新标准c++程序设计

    游戏软件的开发最能体现面向对象设计方法的优势.游戏中的人物.道具.建筑物.场景等都是很直观的对象,游戏运行的过程就是这些对象相互作用的过程.每个对象都有自己的属性和方法,不同对象也可能有共同的属性和方 ...

  9. 复制构造函数被调用的三种情况------新标准c++程序设计

    1.当用一个对象去初始化同类的另一个对象时,会引发复制构造函数被调用.例如,下面的两条语句都会引发复制构造函数的调用,用以初始化c2. C c2 (c1); C c2=c1; 这两条语句是等价的.注意 ...

随机推荐

  1. java NIO(转载)

    (原文地址:https://zhuanlan.zhihu.com/p/23488863) NIO(Non-blocking I/O,在Java领域,也称为New I/O),是一种同步非阻塞的I/O模型 ...

  2. jgrid相关功能用法记录

    1.获取行号var ids = $gridList.jqGrid('getGridParam', 'selarrrow'); //多选,返回选中行号组字符 var ids2 = $gridList.j ...

  3. cs231n神经网络 常用激活函数

    CS231n课程笔记翻译:神经网络笔记1(上) 一.常用激活函数 每个激活函数(或非线性函数)的输入都是一个数字,然后对其进行某种固定的数学操作.下面是在实践中可能遇到的几种激活函数: ——————— ...

  4. DDD学习笔录——提炼问题域之与领域专家一起获得领域见解

    业务和开发团队之间的协作是DDD必不可少的部分,并且它是处于开发阶段的产品获得成功的关键. 领域专家指的是那些从业务领域的政策和工作流程到棘手处和特性都具有深刻理解的人.能够为你的问题区域提供深刻见解 ...

  5. Spring Cloud Config 1 (分布式配置中心)

    spring cloud config是spring cloud团队创建的一个全新的项目,用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持,它分为服务端和客户端两部分. 服务端也被称为 ...

  6. BIO与NIO、AIO的区别(转)

    IO的方式通常分为几种,同步阻塞的BIO.同步非阻塞的NIO.异步非阻塞的AIO. 一.BIO 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSock ...

  7. 尝试在centos5下运行phantomjs2

    在redhat5上运行plantomjs 2,出现如下错误 bin/phantomjs: /lib64/libz.so.1: no version information available (req ...

  8. Centos手动编译安装vim8

    系统:CentOs6.9 gcc版本:5.1.0 github上拉取vim工程之后,cd src,执行一下命令: $ ./configure $ sudo make gcc -c -I. -Iprot ...

  9. 记一篇Python学习的简易版教程

    廖雪峰的教学博客https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143178 ...

  10. golang hello

    package main import "fmt" func main() { fmt.Printf("Hello, world.\n") }