刚开始编程的时候,我相信大家都跟我一样,是这样把两个类联系起来的(现用类A和类B举例):
class A
{
private:
B *b;
test1;
}
这样,当a需要的时候可以调用B类的函数方法
这样的缺点是:
1:A可以使用B的方法,B不可以使用A的方法(B看不到A);
2:内聚性弱,也就是a对象消失b对象一定消失(想像一下a,b是两个窗口,a是登陆,b是主页,当点击a上的按钮时生成b,但a界面不能消失释放,但实际情况下登陆成功后登陆界面消失),b对象生成失败a对象也就失败。
3:如果三个类,四个类,五个类之间交流,互相交流,但上述方法不可能实现
这个问题一直困扰了我很久,上述简单处理虽然可以解决一些基本的问题,但事实上两个类是如何通信 的呢?
如果B要访问A中的test1,不可能直接访问,但是A即可访问本类成员,也可访问B的成员,因此可以在A中设置test1作为参数直接传给B中的成员,或者通过函数形式春给B。该方法的缺点也在于此,要动用A。
如果B要访问A中的函数,???能传函数指针吗。???
B调用A的回调函数,肯定可以。回调函数的定义和使用都在B中,但是设定回调函数需在A中。
A访问B的话,可以调用B的指针访问,或者A的函数包含B的函数,包含B的成员等。
如果A与B没有任何关系,则用友元函数。 全局变量
基本的思想:如果本类中无法访问某个变量或者函数,首先找到具有权限的类。通过该类的权限,间接访问它。
其实方法有很多,大体思路是这样的:
定义一个类M,在M中让A和B作为其成员变量,(这样M中的函数就可以调用A,B中的函数方法),当A中想要发消息给B时,想方设法把消息给M,M再调用B中的函数传给B,那么这个"想方设法"是什么方法呢?
开始我是这么想的
M::M()
{
a=new A(this);//把当前的this指针传给a,这样在a的函数里就可以调用M的函数了。
}
编译会发生错误
为什么捏? 是这样滴:在写类M的时候,要包含头文件#include“A.h”有木有!!,在写类A的函数的时候要包含头文件#include"M.h"有木有!!(因为在A的构造里要定义一个M类型的指针做实参啊!),这里就有问题,计算机执行时,1:走到#include“A.h”这一行代码时要先看看A.h里有什么。2:走到A.h里的时候,发现有#include"M.h"这行代码,然后又进入M.h看看,3:执行1步骤。。。。。是不是循环,无限循环有木有!!!所以报错。
解决方法有很多,例如监听A的函数,利用函数指针,利用全局函数(全局函数简单好用,但破坏了面向对象的封装性)
好了,不罗嗦了,正确答案如下:
用接口函数,interface,在c++下没有定义接口函数,其实接口函数就是纯虚函数,在vc下(别的我不知道行不行)可以这样:
纯虚类是因为class不产生虚表,只能在派生类中实现虚表;C++中没有提供类似interface这样的关键字来定义接口,但是Mircrosoft c++中提供了__declspec(novtable)来修饰一个类,来表示该类没有虚函数表,也就是虚函数都(应该)是纯虚的。减小SIZE 是因为虚表是需要空间的,在不需要虚表的情况下,把虚表去掉就可以减少SIZE了。
#include <IOSTREAM>
using namespace std;
#define interface class __declspec(novtable)
interface InterFace
{
virtual void f();
};
为了解决那个让计算机迷糊的问题,我们让M继承InterFace,然后传参的时候传InterFace类型的,这样就不会重复包含了,试试:
#include"Interface.h"
#include"A.h"
#include"B.h"
class M :public InterFace//继承必须包含头文件定义,声明没有用
{
private:
A *a;
B *b;
public:
M()//构造
{
a=new A(this);//因为M继承InterFace所以可以用父类的指针来作为它的实参!
b=new B();
}
void f()
{
b->show();//调用B类方法
}
};
在A类:
#include"InterFace.h"
class A
{
public:
A(InterFace *i)
{
printf("A要调用M中的f()函数,让f()函数调用B的函数,这样A就成功通信到了B!");
i->f();//这里调用的是InterFace的f函数,不过在M类中实例化了
}
};
在B类:
#include"stdio.h"
class B
{
public:
void show()
{
printf("我被M调用了!");
}
};
int mian()
{
M m;
return 0;
}
累死我了!!如有纰漏,望请见谅()以上皆为小冯同学总结,大家复制粘贴的时候不要把这句话删了,3Q!!