首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模板方法模式混乱

模板方法模式混乱
EN

Stack Overflow用户
提问于 2013-12-31 10:46:33
回答 2查看 147关注 0票数 0

在这里,钩子函数本身需要检查也属于类层次结构的数据成员的typeid。所以我为类层次结构定义了一个模板方法。这就是我遇到的乱局:

代码语言:javascript
复制
void Person::leave() {
    // code
    hook();  // private virtual 
    // code
}

void Girl::hook() {  // Girl is a derived class of Person, with data member location 
                 // of type Location which itself has a derived class House
    // code
    location.locationHook(this);// what happens here depends on what kind of location she is in
    // code
}

void Location::locationHook(Person* person) {
    // Oh oh!  This depends on what class person is
}

void House::locationHook(Person* person) {
    // Oh oh!  This depends on what class person is

}

因此,对于这种情况,我不得不求助于我原来的方法,即使用typeid(* Person )和每种Person派生类的dynamic_cast和if-语句来定义虚拟locationHook,对吧?

EN

回答 2

Stack Overflow用户

发布于 2013-12-31 13:09:00

这就是我想出的解决方案。我测试了它的工作,但我不知道它是否得到了任何批准(或者它是否总是有效):

代码语言:javascript
复制
void Person::leave() {
    // code
    hook();
}

void Person::hook() {
    // code
    location.locationHook (this);
}

void Girl::hook() {
    // code 
    location.locationHook (this);
}

void Location::locationHook (Person* person) {
    // code
    person->removeFromLocation();
}

void House::locationHook (Person* person) {
    // code 
    person->removeFromHouse();
}

// removeFromLocation() and removeFromHouse() are also virtual functions of Person
票数 0
EN

Stack Overflow用户

发布于 2016-04-03 06:20:24

以下是使用双重分派的替代解决方案:

代码语言:javascript
复制
#include <iostream>
#include <list>

struct Person;  struct Girl;  struct Guy;

struct Location {
    virtual void hook (Person*) = 0;
    virtual void hook (Girl*) = 0;
    virtual void hook (Guy*) = 0;
};

struct House : Location {
    virtual void hook (Person*) override;
    virtual void hook (Girl*) override {
        std::cout << "Girl left the house.\n";
    }
    virtual void hook (Guy*) override {
        std::cout << "Guy left the house.\n";
    }
};

struct Person {
    Location* location = new House;
    void leave() {
        // ...
        hook();
        // ...
    }
    virtual void invoke_hook (Location*) = 0;
private:
    virtual void hook() = 0;
};

struct Girl : Person {
    virtual void hook() override { 
        std::cout << "Girl will leave the house.\n";
        location->hook(this);
        // ...
    }
    virtual void invoke_hook (Location* location) override { location->hook(this); }  // Double dispatch
};

struct Guy : Person {
    virtual void hook() override { 
        std::cout << "Guy will leave the house.\n";
        location->hook(this);
        // ...
    }
    virtual void invoke_hook (Location* location) override { location->hook(this); }  // Double dispatch
};

void House::hook (Person* person) {
    person->invoke_hook(this);  // Double dispatch
}

int main() {
    std::list<Person*> people = {new Girl, new Guy};
    for (Person* p : people)
        p->leave();  // Simple overloads will do the job here.

    House* house = new House;
    for (Person* p : people)
        house->hook(p);  // Double dispatch used.
}

输出:

代码语言:javascript
复制
Girl will leave the house.
Girl left the house.
Guy will leave the house.
Guy left the house.
Girl left the house.
Guy left the house.
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20850980

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档