Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Loki::AbstractFactory, Не понятно назначение кода в исходнике 
:(
    Опции темы
Chaos A.D.
Дата 23.7.2005, 22:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



В библиотеке Loki в реализации паттерна AbstractFactory есть такой код...
Код

template
<
    class TList,
    template <class> class Unit = AbstractFactoryUnit
>
class AbstractFactory : public GenScatterHierarchy<TList, Unit>
{
    public:
        typedef TList ProductList;
    
        template <class T> T* Create()
        {
            Unit<T>& unit = *this;
            return unit.DoCreate(Type2Type<T>());
        }
};


Мне не совсем понятно, зачем делать срез в следующем коде - Unit<T>& unit = *this;. Ясно одно - без него вызов виртуальной функции DoCreate у Unit<T> считается неоднозначным. Но почему?
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
Earnest
Дата 25.7.2005, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Я, к сожалению, не знаю, как устроена библиотеку Loki, но раз вызов может быть неоднозначным, то, возможно, где-то в иерархии наследования AbstractFactory встречается либо множественное наследование от Unit (или его базового класса), либо кто-то еще в иерархии имеет метод DoCreate. А может AbstractFactory вовсе не наследуется от Unit, а просто имеет оператор приведения...



--------------------
...
PM   Вверх
Void
Дата 25.7.2005, 19:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Earnest
Так точно. GenScatterHierarchy наследуется от Unit, специализированного каждым типом из списка типов TList.

Все подробно у Александреску в "Modern C++ Design" расписано.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Earnest
Дата 25.7.2005, 22:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Точно, у Александреску я про это и читала - то-то я смотрю, слова все какие-то знакомые smile
Однако мне всегда казалось, что реализовать основные паттерны в виде шаблонов - интересно, конечно, теоретически - в смысле очередного доказательства всемогущества C++. Но с практической точки зрения, лучше некоторые вещи делать под свой проект самим... ИМХО, конечно.


--------------------
...
PM   Вверх
LPBOY
Дата 29.7.2005, 23:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 228
Регистрация: 12.7.2005

Репутация: 20
Всего: 20



Цитата(Chaos @ 23.7.2005, 22:28)
Мне не совсем понятно, зачем делать срез в следующем коде - Unit<T>& unit = *this;

Что значит "срез"?
--------------------
Каждый человек по-своему прав, а по-моему нет...
PM MAIL   Вверх
comcon1
Дата 30.7.2005, 12:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 838
Регистрация: 11.6.2005
Где: Москва ДАС-МГУ

Репутация: 12
Всего: 17



Сорри за оффтопик, но где брать доки по Loki. Кроме solarix.ru - там неполная. Я че-т у Александревску не нашел smile


--------------------
PM MAIL   Вверх
Chaos A.D.
Дата 30.7.2005, 19:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



А кстати, почему так получается, что если у нас есть класс A с виртуальной функцией MakeSomething(int), и класс B с виртуальной функцией с аналогичным именем, но с параметром char, то при выведении класса AB из A и B, вызов AB::MakeSomething('x') или AB::MakeSomething(4325) считается неоднозначным?
Добавлено @ 20:01
Цитата(LPBOY @ 29.7.2005, 23:54)
Что значит "срез"?

Вообще в моем примере я ошибся, это не то, что называется срезом. А вообще, срез - это когда объект базового класса создается из производного. Например, если кидать исключение класса B, а поймать по значению класса A, который является базовым для B, данные из B, не содержащиеся в A потеряются. Чтобы этого избежать, нужно ловить исключения например по ссылке. Это только пример среза.
Добавлено @ 20:06
Цитата(comcon1 @ 30.7.2005, 12:42)
Сорри за оффтопик, но где брать доки по Loki. Кроме solarix.ru - там неполная. Я че-т у Александревску не нашел

Имхо после книги Александреску "Modern C++ Design" про Loki вряд-ли можно что-нибудь сказать.

Это сообщение отредактировал(а) Chaos A.D. - 30.7.2005, 20:09
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
Chaos A.D.
Дата 30.7.2005, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7




Цитата(Earnest @ 25.7.2005, 22:01)
...Однако мне всегда казалось, что реализовать основные паттерны в виде шаблонов - интересно, конечно, теоретически - в смысле очередного доказательства всемогущества C++. Но с практической точки зрения, лучше некоторые вещи делать под свой проект самим... ИМХО, конечно.


Я нашел крайне удобным шаблонный класс Functor, реализацию паттерна Command, по моему. Так-же очень удобно, и, имхо, на все случаи жизни, реализован Smart Pointer. Классно написан Singleton. Если бы мне надо было бы написать функтор самому, я бы попытался переписать его так же, как написал его Александреска. По моему, функторы у него просто образцово-показательные smile.
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
Void
Дата 30.7.2005, 20:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Цитата(Chaos @ 30.7.2005, 21:57)
А кстати, почему так получается, что если у нас есть класс A с виртуальной функцией MakeSomething(int), и класс B с виртуальной функцией с аналогичным именем, но с параметром char, то при выведении класса AB из A и B, вызов AB::MakeSomething('x') или AB::MakeSomething(4325) считается неоднозначным?

Насколько я понимаю, overload resolution (13.3) выполняется, только если функция-член была найдена однозначно (Member name lookup, 10.2). Вроде так.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
LPBOY
Дата 30.7.2005, 21:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 228
Регистрация: 12.7.2005

Репутация: 20
Всего: 20



Цитата


А кстати, почему так получается, что если у нас есть класс A с виртуальной функцией MakeSomething(int), и класс B с виртуальной функцией с аналогичным именем, но с параметром char, то при выведении класса AB из A и B, вызов AB::MakeSomething('x') или AB::MakeSomething(4325) считается неоднозначным?



Для того чтобы перегрузка функций имела место надо чтобы все функции находились
в одной и той же области видимости. В твоем примере они находятся в разных областях.
Отсюда вывод: помести их в область класса AB с помощью using объявлений, тогда перегрузка будет работать. Иначе надо просто явно указывать базовый класс: A::MakeSomething или B::MakeSomething.

Это сообщение отредактировал(а) LPBOY - 30.7.2005, 21:16
--------------------
Каждый человек по-своему прав, а по-моему нет...
PM MAIL   Вверх
Chaos A.D.
Дата 31.7.2005, 12:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



Странные вещи творятся... В Евангилие от Страуструпа я докопался вот до чего : "Разрешение перегрузки не пересекает границ областей видимости классов. В частности, неоднозначности между функциями из различных базовых классов не разрешаются на основе типов аргументов.". Это можно считать исчерпывающим ответом на мой предыдущий вопрос. Но если ввести обе функции из базовых классов в область видимости производного класса при помощи using-объявления, все становится на свои места... Однако не все так мажорно. Если мои функции из базовых классов виртуальные, вызывается всегда только одна, причем её фактический параметр, похоже, reinterpret_cast-ится к типу формального параметра. Очень удивило меня, когда функция, принимающая std::string, вдруг приводила его к типу double. Как я понимаю, у класса, подобного моему из примера, два указателя на таблицы виртуальных функций, но как это сказывается на виртуальном вызове из моего примера? Как там это оговорено в стандарте?
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
Void
Дата 31.7.2005, 12:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Chaos A.D.
Можно код в студию? И версию компилятора. Если я правильно понял проблему, VC 7.1 подобную ситуацию отрабатывает нормально.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Chaos A.D.
Дата 31.7.2005, 13:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



Void, ты прав, дело в компилере. Глючный Борландовский компилер компилил с ошибками, неполенился скомпилить это дело в линухе с G++, все заработало. Попробуйте, у кого есть компилер от Borland, скомпилить этот код. А как подобный код обрабатывают другие компилеры (Comeau, Intel-овский)?

Код

#include <iostream>
#include <string>

#ifdef __BORLANDC__
    #include <conio>
#endif

class Foo
{
    public :
        virtual void Fn( std::string str )
        { std::cout << "Foo::Fn(" << str << ") called;" << std::endl; };
};

class Bar
{
    public :
        virtual void Fn( double d )
        { std::cout << "Bar::Fn(" << d << ") called;" << std::endl; };
};

class Banana : public Foo, public Bar
{
    public :
        using Foo::Fn;
        using Bar::Fn;
};

int main(int argc, char *argv[])
{
    Banana *b = new Banana;
    b->Fn("Hello");
    b->Fn(43.21);
    #ifdef __BORLANDC__
        getch();
    #endif
}

--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
LPBOY
Дата 31.7.2005, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 228
Регистрация: 12.7.2005

Репутация: 20
Всего: 20



Цитата(Chaos @ 31.7.2005, 13:08)
Попробуйте, у кого есть компилер от Borland, скомпилить этот код.

Попробовал...
Цитата(Chaos @ 31.7.2005, 13:08)
А как подобный код обрабатывают другие компилеры (Comeau, Intel-овский)?

Проверил в своих MSVC 7.1, Digital Mars 8.4.3, работает нормально. Так что это конечно баг дебилдера.
--------------------
Каждый человек по-своему прав, а по-моему нет...
PM MAIL   Вверх
Void
Дата 31.7.2005, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Chaos A.D.
VC 7.1, VC 8.0 beta 2, Intel 7.1 (Win), GCC 3.4.2 (MinGW), даже малоизвестный DigitalMars 8.41 компилят нормальный код (по поводу Comeau я даже сомневаться не буду). А это угребище Borland C++ 5.6 aka BCB6 - нет! Всерьез не завидую тем, кто вынужден иметь с ним дело.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0819 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.