Шаблонный метод шаблонный беспорядок

Здесь функции ловушки сами должны проверять 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 и операторов if для каждого типа производного класса Person для определения виртуального locationHook’s, верно?

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
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.
0

По вопросам рекламы [email protected]