zoukankan      html  css  js  c++  java
  • C++ 类之间的互相调用

    这几天做C++11的线程池时遇到了一个问题,就是类A想要调用类B的方法,而类B也想调用类A的方法

    这里为了简化起见,我用更容易理解的观察者模式向大家展开陈述

     

    观察者模式:在对象之间定义一对多的依赖,这样一来,当一个对象改变状态时,依赖它的对象都会收到通知,并自动更新

    image

    观察者模式中有一个subject和observer

    observer向subject注册成为一个观察者

    当subject发生改变时,它通知所有的观察者

    当一个observer不想作为观察者时,它会向subject发出请求,将自己从观察者中除名

     

    注意,在这里是存在一个互相调用的

    subject肯定需要知道observer的方法,这样它才能在状态发生改变时调用observer的方法通知他们

    而当一个observer想要将自己从观察者中除名的时候,它需要保留一个subjet的引用,并让subject调用remove方法将自己除名

     

    为了简化起见

    在这里的类图如下

    image

     

    在java,我们可以这样实现

    复制代码
    import java.util.ArrayList;class Subject {
    public void change() {

    for (Observer x :observerList) {
    x.Show();
    }
    }
    public void register(Observer o) {
    observerList.add(o);
    }
    public void Remove(Observer o) {
    observerList.remove(o);
    }
    private ArrayList<Observer> observerList=new ArrayList<Observer>();
    }
    class Observer {
    public void Show() {
    System.
    out.println("I konw The Subject is changed");
    }
    public Observer(Subject s) {
    subject
    = s;
    }
    public void Remove() {
    subject.Remove(
    this);
    }
    private Subject subject;
    }
    public class Observertry {
    public static void main(String[] args) {
    Subject s
    = new Subject();
    Observer o
    = new Observer(s);
    s.register(o);
    s.change();
    }
    }
    复制代码

    运行结果

    image

     

    而在C++中

    如果我们在main.cpp中编写出以下代码

    复制代码
    #include <iostream>
    #include <string>
    #include <vector>using namespace std;class Observer;class Subject;class Observer
    {
    public:
    Observer(Subject
    *s)
    {
    subject
    = s;
    }
    void Remove(Subject *s)
    {
    s
    ->Remove(this);
    }
    void Show()
    {
    cout
    << "I konw Subject is change" << endl;
    }
    private:
    Subject
    *subject;
    };
    class Subject
    {
    public:
    void change()
    {
    for (vector<Observer*>::iterator it = observerlist.begin(); it != observerlist.end(); it++)
    {
    (
    *it)->Show();
    }

    }
    void Remove(Observer *o)
    {
    observerlist.erase(find(observerlist.begin(), observerlist.end(), o));
    }
    void Register(Observer *o)
    {
    observerlist.push_back(o);
    }
    private:
    vector
    <Observer*> observerlist;

    };
    int main()
    {
    Subject s;
    Observer o(
    &s);
    s.Register(
    &o);
    s.change();
    system(
    "pause");
    }
    复制代码

    会发现这段代码无法编译通过

    在vs2013中会有以下error

    image

    这是因为虽然有类的成员的前向声明

    但你仅可以定义指向这种裂隙的指针或引用,可以声明但不能定义以这种不完全类型或者返回类型的参数

    而这里你想要在Observer类里调用subject的方法,而subject是在Observer的后面声明定义的,所以无法调用subject的方法

    而C++是没有对类的函数的前向声明的

    所以我们要有一个方法,让我们在声明类Subject时能看到类Observer的声明

    而在声明类Observer时,能看到类Subject的声明

     

    所以我们想到将Subject和Observer分别放到两个文件中去

    所以我们有了如下尝试

    subject.h

    复制代码
    #pragma once
    #include "Observer.h"
    #include <iostream>
    #include <vector>class Subject
    {
    public:
    void change();
    void Remove(Observer *o);
    void Register(Observer *o);
    std::vector
    <Observer*> observerlist;
    };
    复制代码

    observer.h

    复制代码
    #pragma once
    #include <iostream>
    #include "Subject.h"
    using namespace std;class Subject;class Observer
    {
    public:
    Observer(Subject
    *s);

    void Remove(Subject *s);
    void Show();
    Subject
    *subject;
    };
    复制代码

    但这一次依旧无法通过编译

    因为我们这里出现了头文件的互相包含

    subject.h中包含了observer.h

    observer.h中包含了subject.h

     

     

    所以正确的方法是把其中的一个的include放到相应的实现文件中即cpp文件中

    代码如下

    subject.h

    复制代码
    #pragma once
    #include "Observer.h"
    #include <iostream>
    #include <vector>class Subject
    {
    public:
    void change();
    void Remove(Observer *o);
    void Register(Observer *o);
    std::vector
    <Observer*> observerlist;
    };
    复制代码

    subject.cpp

    复制代码
    #include "Subject.h"
    void Subject::change()
    {
    for (vector<Observer*>::iterator it = observerlist.begin(); it != observerlist.end(); it++)
    {
    (
    *it)->Show();
    }
    }
    void Subject::Remove(Observer *o)
    {
    observerlist.erase(find(observerlist.begin(), observerlist.end(), o));
    }
    void Subject::Register(Observer *o)
    {
    observerlist.push_back(o);
    }
    复制代码

     

    observer.h

    复制代码
    #pragma once
    #include <iostream>using namespace std;class Subject;class Observer
    {
    public:
    Observer(Subject
    *s);

    void Remove(Subject *s);
    void Show();
    Subject
    *subject;
    };
    复制代码

    observer.cpp

    复制代码
    #include "Observer.h"
    #include "Subject.h"
    Observer::Observer(Subject *s)
    {
    subject
    = s;
    }
    void Observer::Remove(Subject *s)
    {
    s
    ->Remove(this);
    }
    void Observer::Show()
    {
    cout
    << "I know Subject is changed" << endl;
    }
    复制代码

    我们将#include “Subject.h”放到了observer.cpp中

    这样就在observer的实现中就可以看到Subject的声明,进而调用subject的Remove方法,有不会引起互相包含的问题了

    运行结果如下

    image

  • 相关阅读:
    [数据库]Oracle数据迁移至HIVE(待续)
    [Java EE]解决浏览器跨域问题
    [Linux]Xmanager+Xshell远程管理桌面版CentOS物理服务器的桌面版CentOS虚拟机
    JAVA生成随机数工具类RandomStringUtils详解
    electron 安装不同的版本的方法
    Git 常用操作(一)
    openresty 简单入门
    Ubuntu 分辨率设置
    javascript尾调用与尾递归
    深入理解 JavaScript 执行上下文和执行栈
  • 原文地址:https://www.cnblogs.com/Anzhongliu/p/6091773.html
Copyright © 2011-2022 走看看