В моем приложении есть класс, для которого мне нужно сохранить набор интерфейсов, предоставляемых приложением.
Поскольку сам класс не знает всех возможных интерфейсов, он не может просто сохранить один элемент данных для каждого интерфейса. Вместо этого он должен сохранять вектор интерфейсов.
На практике это означает, что я определяю один «универсальный» интерфейс (IGeneric), который наследуют все более специфические интерфейсы. Таким образом, я могу легко сохранить вектор со всеми интерфейсами (в приведенном ниже коде я заменил фактические имена интерфейсов на некоторые фиктивные имена; в моем приложении имена гораздо более значимы):
#include <vector>
#include <windows.h>
class IGeneric
{
public:
virtual ~IGeneric() {}
};
class IFirst : public IGeneric {public: virtual void one() = 0;};
class ISecond : public IGeneric {public: virtual void two() = 0;};
class IThird : public IGeneric {public: virtual void three() = 0;};
class IFourth : public IGeneric {public: virtual void four() = 0;};
typedef std::vector<IGeneric *> GenericContainer;
Для установки интерфейсов другие модули (которые действительно знают все интерфейсы) предоставляют функции для установки интерфейсов. Они могут быть примерно такими:
void installFirst (GenericContainer &bc, IFirst &b) { bc.push_back(&b); }
void installSecond (GenericContainer &bc, ISecond &b) { bc.push_back(&b); }
void installThird (GenericContainer &bc, IThird &b) { bc.push_back(&b); }
void installFourth (GenericContainer &bc, IFourth &b) { bc.push_back(&b); }
На практике приложения будут писать классы, которые реализуют несколько из этих интерфейсов, например:
class DoAll : public IFirst, public ISecond, public IThird, public IFourth
{
public:
virtual void one() {}
virtual void two() {}
virtual void three() {}
virtual void four() {}
DoAll(int i) : m_i(i) {}
private:
int m_i;
};
Установка этой реализации теперь действительно проста. Это основная процедура из моего примера:
int main ()
{
GenericContainer gc;
DoAll all (123);
installFirst (дс, все);
installSecond (дс, все);
installThird (дс, все);
installFourth (дс, все);
* * DebugBreak тысячи двадцать-три ();
}
В точке останова я теперь исследую содержимое вектора в отладчике. Это выглядит так:
![alt text](https://i.stack.imgur.com/p2jRa.png)
Как вы можете видеть, это показывает, что реализация интерфейсов - это DoAll (во всех 4 случаях), и даже показывает, какой интерфейс (IFirst, ISecond, ...) DoAll был установлен в векторе.
Проблема в том, что отладчик не может показать содержимое самого производного класса (DoAll). В нем показан дата данных m_i, но невозможно отобразить значение m_i.
Только если я явно возьму первый адрес интерфейса и приведу его к «DoAll *», я смогу правильно увидеть содержимое:
![alt text](https://i.stack.imgur.com/9EXcl.png)
Я компилирую и связываю, используя следующие команды:
cl /c /EHsc /GR /Zi /Od test.cpp
link /debug test.obj
Это ошибка в Visual Studio 2010 или я что-то упустил?
EDIT:
Если я использую одиночное наследование, как в этом классе:
class DoFirst : public IFirst
{
public:
virtual void one() {}
DoFirst(int i) : m_i(i) {}
private:
int m_i;
};
И установите его в векторе так:
DoFirst f (456);
installFirst (gc,f);
Отладчик показывает мне правильные значения, а также сразу показывает самый производный класс:
![alt text](https://i.stack.imgur.com/k7ywL.png)