Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > как вывести такой вектор?


Автор: Alek86 21.3.2008, 17:37
сразу предупрежу, что тема создана не только на этом форуме, но уж очень желательно сегодня мне с ней разобраться...

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

дана такая вот иерархия структур и вектор, заполненный ими:
Код

struct Interface {};

template<typename T>
struct Struct1 : Interface {
  Struct1(int i) : m_i(i) {}
  int m_i;
};

template<typename T>
struct Struct2 : Interface {
  Struct2(int i1, int i2) : m_i1(i1), m_i2(i2) {}
  int m_i1, m_i2;
};

int main() {
  std::vector<Interface*> vect;
  vect.push_back(new Struct1<int>(1));
  vect.push_back(new Struct2<int>(1, 2));
  vect.push_back(new Struct1<char>(433));
  vect.push_back(new Struct2<double>(3, 4));
  vect.push_back(new Struct2<float>(12, 344));
  vect.push_back(new Struct1<double>(143));

  PrintVector(vect);
}



нужно написать функцию, которая сможет вывести этот вектор.
Естественно, вектор может быть заполнен в какой угодно последовательности...
+ условие - структуры трогать нельзя - ни добавлять ни менять, ни удалять. Они - в ридонли коде. 

Добавлено Сегодня, 17:33
кстати, для решения разрешены любые боле-мене стандартные уловки - и динамиккаст и т.п.

Автор: JackYF 21.3.2008, 17:43
Цитата(Alek86 @  21.3.2008,  16:37 Найти цитируемый пост)
кстати, для решения разрешены любые боле-мене стандартные уловки - и динамиккаст и т.п.

Ну, нормальное решение, имхо, в Intefrace virtual print(std::stringstream&).
Делать разные структуры, а потом их выводить "единообразно" без общих методов - имхо, нагло.

Если же кровь из носа и трогать нельзя совсем - проходимся по вектору, делаем столько dynamic_cast'ов, сколько структур у нас имеется, проверяя от предка к родителям, и выводя члены определённой структуры.

Добавлено через 31 секунду
З.Ы. Alek86, про кнопку "Код" ты зря забыл smile

Автор: Alek86 21.3.2008, 17:55
Цитата(JackYF @  21.3.2008,  17:43 Найти цитируемый пост)
 Alek86, про кнопку "Код" ты зря забыл 

исправил smile


Цитата(JackYF @  21.3.2008,  17:43 Найти цитируемый пост)
проходимся по вектору, делаем столько dynamic_cast'ов, сколько структур у нас имеется, проверяя от предка к родителям, и выводя члены определённой структуры.

можешь этот кусок в коде?
у меня как раз нестыковка с динамик кастами и шаблонами - куда кастить?

Автор: Alek86 21.3.2008, 18:34
вроде как решения по условию задачи не существует.
вопрос решен

Автор: bsa 21.3.2008, 19:10
А помоему имеет. Схожая задача описана в "современное проектирование на С++" А. Александресску (мультиметоды).

Автор: Alek86 21.3.2008, 19:18
можно тогда примерный вид функции PrintVector?

Автор: bsa 21.3.2008, 19:25
блин. там очень сложно. создается список возможных типов StructN, затем список возможных параметров этих StructN (int, char, double...), затем генерируется список возможных комбинаций и из этого списка генерируется набор функций вывода...
Код я так запросто тут не напишу. Это довольно объемный текст получится. Проще http://files.zipsites.ru/books/programming/moderncppdesign_rus.zip и посмотреть. smile

Автор: JackYF 21.3.2008, 20:07
Цитата(bsa @  21.3.2008,  18:10 Найти цитируемый пост)
Схожая задача описана в "современное проектирование на С++" А. Александресску (мультиметоды).

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

Автор: bsa 22.3.2008, 00:15
Цитата(JackYF @ 21.3.2008,  20:07)
Омф. А они-то тут причём? тут загвоздка в том, что в иерархию классов нельзя добавить нужную виртуальную функцию. Мультиметоды - это же расширение виртуальных функций на зависимость от типа двух и более объектов?

Если честно, я читал эту тему "по диагонали". Уж очень она какой-то абстрактной мне показалась. Поэтому могу чего-то перепутать.
Просто в той книжке рассматривался ряд случаем, компоновка которых может дать решение этой задачи. Но, имхо, проще добавить виртуальный метод в интерфейс...  smile 

Автор: blinded 22.3.2008, 12:36
Структуры трогать нельзя, а вектор трогать можно? Это обязательно должен быть вектор Interface*?

Автор: Alek86 22.3.2008, 18:01
blinded, условие задачи - вообще написать функцию smile
то есть ничего трогать нельзя

Автор: korian 22.3.2008, 18:30
хак методом:
Код

struct Interface {
    virtual ~Interface();
};

void PrintVector(const std::vector<Interface*>& vect)
{
    for (std::vector<Interface*>::const_iterator iter = vect.begin(); iter != vect.end(); ++iter)
    {
        std::string str = typeid(*(*iter)).name();
        str.resize(7);
        if (str == "Struct1")
        {
            int* i = reinterpret_cast<int*>(*iter);
            std::cout<<i[1]<<std::endl;
        }
        else if (str == "Struct2")
        {
            int* i = reinterpret_cast<int*>(*iter);
            std::cout<<i[1]<<", ";
            std::cout<<i[2]<<std::endl;
        }
    }
}

правда все равно надо добавлять в Interface хотя бы виртуальный деструктор. Его правда полюбому надо добавлять, т.к. такой вектор не то что вывести, его и удалить нормально нельзя.

Автор: bsa 22.3.2008, 19:11
korian, удалить можно... А вот dynamic_cast (как, впрочем, и typeid) вряд ли работать будет без vtable...
Думаю, задача действительно не имеет решения.

Автор: mes 22.3.2008, 19:14
Цитата(korian @  22.3.2008,  18:30 Найти цитируемый пост)
std::string str = typeid(*(*iter)).name();

у меня при исполнении этой строчки кода  str  == "9Interface"

Автор: korian 22.3.2008, 19:16
удалить то можно, я в то смысле, что деструкторы вызываться не будут для Struct-ов.

Автор: Alek86 22.3.2008, 19:16
Цитата(korian @  22.3.2008,  18:30 Найти цитируемый пост)
хак методом:

1. идею понял, правда у меня она не пашет (но идея - хоть кривое, но решение задачи для одного компилятора)

2. не обязательно после
Код
str.resize(7);

сработает
Код
if (str == "Struct1")


3. 
Цитата(korian @  22.3.2008,  18:30 Найти цитируемый пост)
 Его правда полюбому надо добавлять

ну почему же так прям "полюбому"...
Если интерфейс не рассчитан, чтобы с него удаляли, то деструктор может быть обычным (желательно в привате)

Автор: bsa 22.3.2008, 19:19
Цитата(mes @ 22.3.2008,  19:14)
Цитата(korian @  22.3.2008,  18:30 Найти цитируемый пост)
std::string str = typeid(*(*iter)).name();

у меня при исполнении этой строчки кода  str  == "9Interface"

typeid(...).name() возвращает внутреннее имя объекта. Оно может быть любым (в т.ч. и ""). А потом, если у базового класса нет хотя бы одного виртуального метода (обычно, деструктор), то typeid и dynamic_cast не работают.

Автор: korian 22.3.2008, 19:21
ну это понятно, что это работать будет только там где проверено.
у mes вон вообще какое-то "9Interface".

Автор: bsa 22.3.2008, 19:21
Цитата(korian @ 22.3.2008,  19:16)
удалить то можно, я в то смысле, что деструкторы вызываться не будут для Struct-ов.

Меня что-то переглючило и я решил, что речь идет про удаление потомков. smile
Конечно, в данном случае нет практически никакого смысла в этом Interface smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)