C++跨类调用(类间传值、跨类调用方法)
在面向对象编程时,我们经常会遇到不同类的实例之间的跨类调用,包括跨类值传递和跨类调用方法。 在实际应用中,有多种方法可以解决这个问题。 今天我们主要总结两个常用的。 和一般方法。 1、通过全局变量实现跨类调用(一)优点和缺点
优点:简单、快速、易于理解,特别是当类实例数量较少时。
缺点:安全性低,类实例数量较多时非常不方便,且容易出错。
(二)思想原则
定义多个全局指针变量,用来存放各个类各个实例对象的指针(当然他们之间需要互相调用,不调用肯定不会写!!!)。 创建实例化对象后,将全局指针变量指向该实例。 对象,在任何地方(包括类内部)都可以使用这个指针来调用相应的方法并获取相应的成员变量。 注意:每个实例对象对应一个指针,而不是每个类。 目前还不清楚是否可以区分类和实例。
(三)具体流程
下面举例说明具体流程:
例子:A类已有的实例对象a想要获取B类的实例化对象b的成员变量m_b的值。
(a) Ah 和 Bh 不需要任何修改。
(b) B.cpp包含A的头文件,并定义了全局B类指针pB。
CB * pB = new CB;
(c) 在实例化b的.cpp文件中添加
extern CB * pB; //extern表示变量或者函数的定义在别的文件中
(d) 当 b 被实例化时,将 pB 指向 b。
CB * b = new CB(); //调用的构造函数不同时,应该传入参数
pB = b;
注:也可以使用B的构造函数将pB指向b,适用于B类只有一个实例的情况。具体方法是在B.pp中添加
extern CB * pB;
在B的构造函数中添加
pB = this; //构造的实例的指针保存在pB中;
这样就可以在整个项目中随意调用b的成员变量和成员函数了。 当然,调用前需要使用CB * pB; 先声明一下。
2、通过类内指针变量实现跨类调用(一)优缺点
优点:安全性高,非常快速方便,尤其是当类实例较多时。
缺点:比较复杂,理解起来稍有难度。
(二)思想原则
将被调用类的指针添加为类中的成员变量。 被调用类的对象实例化后,将指针(成员变量)指向实例。 然后通过关联的实例就可以完成跨类调用。
(三)具体流程
下面举例说明具体流程:
例子:A类已有的实例对象a想要获取B类的实例化对象b的成员变量m_b的值;
B类的实例对象b想要获取A类的实例化对象a的成员变量m_a的值。
(a) Ah 和 Bh 包含彼此的头文件。
(b) 将B类的指针添加到CA,将A类的指针添加到CB;
CB * pB; //A.h中添加
CA * pA; //B.h中添加
这时候编译连接的时候就会报错,因为这是一个“先有鸡还是先有蛋的问题”
^_^ 如果有兴趣可以研究一下C++的编译和链接过程。 下一步是解决这个问题。
(c) 在 Ah 中的 A 类声明之前添加 B 类声明; 在 Bh 中的 B 类声明之前添加 A 类声明;
class CB; // A.h中A类声明前
class CA; // B.h中B类声明前
(d) 指针实例化各种类型的对象后,将指针指向各个类型的实例对象。
CA* a = new CA(); //注意构造函数
......
CB* b = new CB(); //注意构造函数
// 实例化完成后立即进行关联
a->pB = b;
b->pA = a;
这时就可以使用类内部的指针来访问其他类实例对象的成员变量和成员函数。
说了这么多,相信很多同学都想知道为什么第二种方法这么复杂,它存在的意义是什么。 我简单解释一下第二种方法存在的合理性。
通常我们定义的一个类基本上只有一个或几个类实例对象。 这种情况下,第一种方法可以快速完成开发(除非BOOS不让你使用全局变量)。 但是,如果我们有 100 个 A 类实例对象,并且每个实例对象都需要单独读取或调用 B 类 100 个实例对象之一的成员变量或成员函数,该怎么办? 是不是想想就头晕呢? 这么多的全局变量和对应的对应关系,光是写代码就会出错,毫无安全可言。 这时使用第二种方法可以更快的完成开发。
由于本人能力有限,如有错误还望大神指正。