假设要编写一个小区养狗管理程序,该程序需要一个“主人”类,还需要一个“狗”类。狗是有主人的,主人也有狗。假定狗只有一个主人,但一个主人可以有最多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. djano-cbv模式

    cbv,class base view 就是用类写视图 详细用法替换fbv将在后续空余时间上补齐 fbv,function base view 就是用函数写视图 创建django app01项目 ur ...

  2. mysql安装与基本管理

    一.MySQL介绍 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下公司.MySQL 最流行的关系型数据库管理系统,在 WEB 应用方面MySQL是 ...

  3. Python时间日期函数讲解

    所有日期.时间的api都在datetime模块内. 1. 日期输出格式化 datetime => string import datetime now = datetime.datetime.n ...

  4. Flask之部署

    5.3 部署 当我们执行下面的hello.py时,使用的flask自带的服务器,完成了web服务的启动.在生产环境中,flask自带的服务器,无法满足性能要求,我们这里采用Gunicorn做wsgi容 ...

  5. 关于性能测试中LR的pacing time设置的相关实验

    最近项目中遇到相关性能测试不同方法产生的争议,我这就这个问题在测试环境做了个实验,得出一些指标数据间的有趣关系,供大家讨论学习: 预备知识点: 业界有个TPS ,ART和实际并发量三者间的模拟换算公式 ...

  6. ubuntu12 安装redis和phpRedisAdmin详细流程

    一.Ubuntu安装redis(redis默认端口6379) 方式一.直接下载源码,编译(redis可以编译源码之后直接运行,不需要安装) 1.1执行命令,从官网下载源码编译: $ wget http ...

  7. Hadoop IO基于文件的数据结构详解【列式和行式数据结构的存储策略】

    Charles所有关于hadoop的文章参考自hadoop权威指南第四版预览版 大家可以去safari免费阅读其英文预览版.本人也上传了PDF版本在我的资源中可以免费下载,不需要C币,点击这里下载. ...

  8. Eclipse中建立Maven项目后,Java Resources资源文件下没有src/main/java文件夹

    当建立好一个Maven项目后,在Java Resources资源文件夹下没有看到src/main/java文件夹,然后手动去创建Source Folder时,提示该文件已存在,如图: 有一个解决办法: ...

  9. [iOS]通过xib定义Cell然后关联UICollectionView

    先新建一个View的xib,然后删掉自动生成的View,拖进一个UICollectionCell,再新建一个对应的UIView继承UICollectionCell类. OK,接下来该连outlet的就 ...

  10. Redis搭建(二):主从复制

    一.引言 Redis有三种集群模式: 第一个就是主从模式 第二种“哨兵”模式,在Redis 2.6版本开始提供,2.8版本稳定 第三种是Cluster集群模式,在Redis 3.x以后的版本才增加进来 ...