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

}

したがって、この状況では、typeid(*person) と dynamic_cast を使用する独自の方法に頼る必要があります。また、Person 派生クラスの各タイプに対して if ステートメントを使用して、仮想 locationHook を定義する必要があります。

4

2 に答える 2

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 に答える
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 に答える