2016-05-11 5 views
1

У меня есть иерархия классов:Каков наилучший способ узнать тип объекта отправителя?

class A 
{ 
}; 

class B : public A 
{ 
}; 

class C : public B 
{ 
}; 

class D : public A 
{ 
}; 

и у меня есть некоторые функции, которые выполняет уведомление:

void notify(A* sender, const NotificationType notification) 
{ 
} 

Моя проблема заключается в том, чтобы выяснить точный тип объекта отправителя. Я хочу найти элегантный способ решить эту проблему. Я не люблю использовать динамический бросок для этих целей. Возможный способ заключается в определении перечисления в пределах класса А, как:

enum ClassType 
{ 
    CLASS_A, 
    CLASS_B, 
    CLASS_C, 
    CLASS_D 
}; 

и определение виртуального метода:

virtual ClassType get_type(void) const; 

Но этот подход имеет плохую масштабируемость. Другой способ сохранить эту информацию в NotificationType, но он также имеет плохую масштабируемость.

P.S. Я просто хочу, чтобы использовать подобный код:

Я хочу использовать подобный код:

void notify(A* sender, const NotificationType notification) 
{ 
    if (sender is object of A) 
     new GuiA(); 
    else if (sender is object of B) 
     new GuiB(); 
    else if (sender is object of C) 
     new GuiC(); 
    else 
     new GuiD(); 
} 
+9

«как узнать точный тип объекта отправителя». Если вам нужно знать, вы делаете это неправильно. –

+2

Можете ли вы объяснить, почему вам нужно знать конкретный тип 'sender'? – hansmaad

+4

Кажется странным, что вы разрабатываете приложение для работы полиморфно, а затем чувствуете необходимость знать конкретный тип. –

ответ

2

Если вы хотите знать тип упорствовать иерархии, conside использовать повышение :: TypeIndex (http://www.boost.org/doc/libs/develop/doc/html/boost_typeindex.html).

Если вы хотите, чтобы тип типа обрабатывал разные типы различными способами, используйте Visitor insted идентификатора типа или создавайте абстрактные интерфейсы с виртуальными функциями, которые покрывают ваши потребности.

EDITED

Ваша цель состоит в том, чтобы создать другой объект пользовательского интерфейса для различных типов. Вы можете использовать следующую модель, чтобы достичь своей цели:

class UIObject {...}; 
class UIObjectFactory {...}; 
class A { 
public: 
    virtual std::unique_ptr<UIObject> Create(UIObjectFactory& factory) = 0; 
}; 

void OnNotify(A* sender) { 
    auto ptr = sender->Create(GetUIFactory()); 
    ... 
} 
2

Чтобы создать объект сопоставления с графическим интерфейсом на основе конкретного типа sender, вы можете передать завод в какой-то метод фабрики в A.

class A 
{ 
public: 
    virtual Agui* createGui(GuiFactory& fac) = 0; 
}; 

class GuiFactory 
{ 
public: 
    virtual Agui* forB(B&) = 0; 
    virtual Agui* forC(B&) = 0; 
    virtual Agui* forD(D&) = 0; 
}; 

class B : public A 
{ 
public: 
    Agui* createGui(GuiFactory& fac) 
    { 
     return fac.forB(*this); 
    } 
}; 

void notify(A* sender, const NotificationType notification) 
{ 
    // Use A interface... 
    // Get the concrete GuiFactory from somewhere, and use it 
    auto gui = sender->createGui(win32GuiFactory); 
} 
0

и определение виртуального метода:

virtual ClassType get_type(void) const; 

Самый простой способ для достижения этой цели и избавиться от проблемы масштабирования является реализовать функцию get_type() члена в каждом классе A, B, C , ... таким образом:

typedef uintptr_t ClassType; 
virtual ClassType get_type() const 
{ 
    static int dummy; 
    return reinterpret_cast<ClassType>(&dummy); 
} 

Статическая переменная dummy будет создана для каждого класса, который вы добавите эту функцию-член, так что возвращаемое значение однозначно идентифицирует класс.

Смежные вопросы