Russian Qt Forum
Ноябрь 22, 2024, 18:11 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3 4   Вниз
  Печать  
Автор Тема: Специализация шаблона для базового класса  (Прочитано 23982 раз)
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #15 : Сентябрь 19, 2016, 11:14 »

Основная идея (проблема) в следующем.
Есть закрытая гуй-библиотека, которая содержит разные графические классы.
Некоторые из них имеют общего предка, некоторые нет.
У меня задача расширить функциональность всех этих классов одинаковым образом.
В настоящее время это сделано так, что параллельно к библиотечным существуют "свои" расширяющие классы.
Для того, чтого они могли сосуществовать с гуй-системой, они обязаны быть наследниками библиотечных объектов.
Решено это с помощью multiple inheritance: "свои" классы наследуются от "расширителей" и от гуй-объектов одновременно.
Т.е. так:

// это гуй-библиотека
class GuiBase;
class GuiObjectA : public GuiBase;
class GuiObjectB : public GuiObjectB;
class GuiObjectC : public GuiBase;
---

// это наши "расширители"
class ItemBase;
class ExtItem1: public ItemBase;
class ExtItem2: public ItemBase;
---

// это "расширенные" гуй-классы (идея)
class GuiItemA:  public GuiObjectA, public ExtItem1;
class GuiItemB:  public GuiObjectB, public ExtItem1;
class GuiItemA2:  public GuiObjectA, public ExtItem2;
class GuiItemC2:  public GuiObjectC, public ExtItem2;
и т.д.

проблема в том, что "расширители" должны иметь доступ к гуи-объектам (что при идее выше не будет работать).
Поэтому был слелан соответсвующий темлейт типа

template <class Gui, class Extender>
class GuiItem: public Gui, public Extender
// тут общий функционал, связывающий Gui и Extender

и далее

class GuiItemA:  public GuiItem<GuiObjectA, ExtItem1>;
class GuiItemC2:  public GuiItem<GuiObjectC, ExtItem2>;
...

в некоторых случаях имплементации GuiItem требуется различать между GuiObjectA и GuiObjectC.
Решено с помощью рантайма, хотя мне казалось, что тут как раз шаблоны - самое оно. Но как-то не срастается...
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #16 : Сентябрь 19, 2016, 11:25 »

Накидал небольшой примерчик. Для вашей задачи вроде должен подойти. Но, вроде, тут надо идти другими путями.
https://ideone.com/zeBvoW
Код
C++ (Qt)
#include <iostream>
using namespace std;
 
struct A{
void print() const {cout << "A\n";}
};
 
struct B: public A{
void print() const {cout << "B\n";}
};
 
struct C: public B{
void print() const {cout << "C\n";}
};
 
template<class T>
void print(const T &someClass){
someClass.print();
}
 
int main() {
print(A());
print(B());
print(C());
 
return 0;
}
Цитировать
A
B
C
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #17 : Сентябрь 19, 2016, 11:29 »

проблема в том, что "расширители" должны иметь доступ к гуи-объектам (что при идее выше не будет работать).
Почему не будет работать?
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #18 : Сентябрь 19, 2016, 11:40 »

проблема в том, что "расширители" должны иметь доступ к гуи-объектам (что при идее выше не будет работать).
Почему не будет работать?

Потому что, если написать так:

class GuiItemA:  public GuiObjectA, public ExtItem1;

то ExtItem1 не "видит", что такое GuiObjectA.
Это "знает" только GuiItemA. Но "знать" он должен в зависимости от того, что есть GuiObject...
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #19 : Сентябрь 19, 2016, 11:42 »

Быть может даже и виртуальность не нужна. Обычная перегрузка doStuff поможет?

В том и проблема, что перегружать его надо внутри шаблона, в зависимости от его аргумента (GuiObjectX).
Я как раз этого и хотел добиться, но пока не срастаеццо Грустный
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #20 : Сентябрь 19, 2016, 11:47 »

то ExtItem1 не "видит", что такое GuiObjectA.
Это "знает" только GuiItemA. Но "знать" он должен в зависимости от того, что есть GuiObject...
Так может:
Код
C++ (Qt)
class GuiItemA:  public GuiObjectA, public ExtItem1<GuiObjectA>
 
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #21 : Сентябрь 19, 2016, 11:55 »

Тогда проблема в том, что ExtItem1 будет темплейтом.
А в последующем коде повсеместно юзается dynamic_cast<ExtItem*>(...), что с темплейтом не прокатит Грустный
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #22 : Сентябрь 19, 2016, 12:08 »

Racheengel, имхо, dynamic_cast можно виртуалами заменить. также, посмотрите такую конструкцию
Код
C++ (Qt)
template <class GuiItem>
class ExtendedGuiItemA:  public GuiItem
 
И мне кажется, что вы не посмотрели код в #16
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #23 : Сентябрь 19, 2016, 14:43 »

Racheengel, имхо, dynamic_cast можно виртуалами заменить. также, посмотрите такую конструкцию
Код
C++ (Qt)
template <class GuiItem>
class ExtendedGuiItemA:  public GuiItem
 
И мне кажется, что вы не посмотрели код в #16

Посмотрел, это в принципе практически то же, что и m_ax предложил.
Проблема тут в том, что:
1. из someClass.print() нельзя просто получить доступ к приватным членам вызывающего класса.
2. не все классы имеют метод print(), для некоторых надо вызывать нечто иное.

Виртуалы, _возможно_, были бы решением. Правда, в них придется тащить кучу временных параметров...
Хотя неясно, как поведет себя компиль в таком случае:

class Base;
class Item: Base;
class Item2: Item;

virtual void doStuff(Base* base)
{
// код для Base
}

virtual void doStuff(Item2* item)
{
// код для Item2, но Item2 - тоже наследник Base Грустный
}

имхо тут конфликт будет...
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #24 : Сентябрь 19, 2016, 15:50 »

Цитировать
из someClass.print() нельзя просто получить доступ к приватным членам вызывающего класса.
Соберите тогда все приватные члены в один класс и передавайте объект этого класса в хелпер)
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #25 : Сентябрь 19, 2016, 15:59 »

Основная идея (проблема) в следующем.
Есть закрытая гуй-библиотека, которая содержит разные графические классы.
Некоторые из них имеют общего предка, некоторые нет.
У меня задача расширить функциональность всех этих классов одинаковым образом.
В настоящее время это сделано так, что параллельно к библиотечным существуют "свои" расширяющие классы.
Для того, чтого они могли сосуществовать с гуй-системой, они обязаны быть наследниками библиотечных объектов.
Ну вообще-то это "фабрика" - создать новый класс из разных (или слабо-связных) исходных.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #26 : Сентябрь 19, 2016, 17:29 »

Ну вообще-то это "фабрика" - создать новый класс из разных (или слабо-связных) исходных.
Нет. Фабрика это когда один объект создает другие объекты.
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #27 : Сентябрь 19, 2016, 18:58 »

Цитировать
из someClass.print() нельзя просто получить доступ к приватным членам вызывающего класса.
Соберите тогда все приватные члены в один класс и передавайте объект этого класса в хелпер)

А методы? Улыбающийся Хелперы френдить?
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #28 : Сентябрь 19, 2016, 19:23 »

Цитировать
А методы?  Улыбающийся Хелперы френдить?
Так с таким раскладом здесь проще специализировать ваш T для каждого типа.. Если там всё так сильно друг на друге повязано..
Ну и вообще над архитектурой думать-думать и думать, а уже потом писать)
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #29 : Сентябрь 19, 2016, 23:53 »

Ну и вообще над архитектурой думать-думать и думать, а уже потом писать)

Так уже все "придумано до нас" и изменениям не подлежит.
Наше дело - "расширить" Грустный
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Страниц: 1 [2] 3 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.467 секунд. Запросов: 23.