0

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

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

}

所以对于这种情况,我不得不求助于我的原始方法,即为每种类型的 Person 派生类使用 typeid(*person) 和 dynamic_cast 和 if 语句来定义虚拟 locationHook,对吗?

4

2 回答 2

0

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

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
于 2013-12-31T05:08:59.747 回答
0

这是使用双重调度的替代解决方案:

#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.
}

输出:

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.
于 2016-04-02T22:20:23.897 回答