Форум программистов
 
Регистрация на форуме тут, о проблемах пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail, а тут можно восстановить пароль

Купить рекламу на форуме 15-35 тыс рублей в месяц

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

           Online-курс Java с оплатой после трудоустройства. Каждый выпускник получает предложение о работе
           И зарплату на 30% выше ожидаемой, подробнее на сайте академии, ссылка - https://clck.ru/fCqwP

Ответ
 
Опции темы Поиск в этой теме
Старый 17.08.2016, 23:10   #1
m3g4z0rdEX
Пользователь
 
Регистрация: 14.10.2015
Сообщений: 17
По умолчанию Проблемы с проектированием и дизайном

Здравствуйте, у меня есть некий класс А, чисто виртуальный. От него наследуются другие классы. Затем, что бы использовать функционал виртуальных функций, мне нужно оперировать либо указателями, либо ссылками. И вот, собственно, в другом классе мне нужен Вектор таких вот объектов, в итоге я в классе создаю вектор указателей на базовый класс. Такой подход, требует передачи этого самого вектора указателей в конструктор и т.п При том, что изначально, до создания объекта данного класса мы имеем просто вектор объектов. Да и вообще, для грамотного кеширования хорошо иметь подряд идущие элементы, а не разбросанные созданием через NEW. Естественно, для того чтобы инициализировать свой класс, я создаю вектор указателей, и по вектору объектов беру и заполняю этот вектор, что весьма неудобно. Подскажите, может есть другой, какой способ избежать создание еще одного вектора.... Ведь мне это понятно, а вот другому пользователю, будет уже не очень.
m3g4z0rdEX вне форума Ответить с цитированием
Старый 18.08.2016, 08:35   #2
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,499
По умолчанию

Если я правильно понял вашу проблему, то тут можно прилепить шаблоны.
Код:
template <class T>
class A
{
public:
	virtual void SetVector(std::vector<T*>&) = 0;
};

class B : public A<B>
{
public:
	void SetVector(std::vector<B*> &v)
	{
		v.push_back(new B());
	}
};


int main()
{
	B b;
	std::vector<B*> vB;
	b.SetVector(vB);

    return 0;
}
pu4koff вне форума Ответить с цитированием
Старый 18.08.2016, 10:36   #3
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 673
По умолчанию

Похоже, что вы пытаетесь использовать вируальные функции там, где они просто не нужны. У них весьма узкая специализация - они работают там, где тип объекта с которым будет работать некоторый алгоритм не известен на момент компилции. Например, пользователь вводит с консоли либо 1, либо 2. Если один, то создаём new B, если 2, то new C. Оба (B и C являются наследниками виртуального A). Таким образом, мы избежали написания разных алгоримов отдельно для B и C, а в обоих случаях работаем с A.

Для всего остального (типы известны на момент компиляции) есть шаблоны. Если хотите передавать разные векторы в одну функцию:
Код:
template <typename _T>
void f(std::vector<_T> v) {}
Если хотите передать пачку векторов, то можно так, например:
Код:
template <typename... _T>
void f(_T... t) {}
Правда второй случай требует большей подготовленности (парсинг шаблонного пакета не совсем тривиальная задача. Но ничего сложного, если разобраться).

Если же использовать new очень хочется, а стандартный механизм не устраивает, то можно посмотреть в сторону placement new или в сторону написания своих new/delete либо для класса, либо глобально.
220Volt вне форума Ответить с цитированием
Старый 18.08.2016, 12:25   #4
m3g4z0rdEX
Пользователь
 
Регистрация: 14.10.2015
Сообщений: 17
По умолчанию

Господа, да - шаблоны мне в голову тоже приходили, но тогда, получается так, что этот самый тип, а далее и объект этого пользовательского типа, если будет содержаться в других классах, то и эти классы должны будут быть шаблонными, так ведь ?
Это тоже не очень удобно, да и выглядит странно :?
m3g4z0rdEX вне форума Ответить с цитированием
Старый 18.08.2016, 12:52   #5
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 673
По умолчанию

Навскидку предложу ещё один вариант:
Код:
template <typename _Base>
class Arptr_base
{
public:
  virtual size_t size() = 0;
  virtual _Base &operator[](size_t el) = 0;
  virtual ~Arptr_base() {}
};

template <typename _Base, typename _T>
class Arptr : public Arptr_base<_Base>
{
  std::vector<_T> data;
public:
  Arptr(int size): data(size) {}
  size_t size()override  { return this->data.size(); }
  _Base &operator[](size_t el)override  { return this->data[el]; }
};

class A {};
class B: public A {};

int main()
{
  Arptr_base<A> *arptr = new Arptr<A, B>{20};
  std::cout << arptr->size() << '\n';
  return 0;
}
Это не эталон, указатель в юник птр обвернуть надо, да и вообще чисто демонстрация. Мы получаем Arptr_base<A> одного типа для любых наследников от A. Ещё повторю - с проверкой кода не заморачивался, лишь демонстрация идеи.
220Volt вне форума Ответить с цитированием
Старый 18.08.2016, 16:44   #6
m3g4z0rdEX
Пользователь
 
Регистрация: 14.10.2015
Сообщений: 17
По умолчанию

Ну вот в вашем примере, выше - да, можем создать объект базового класса, указав с треугольных скобках нужный тип, однако, если я буду хранить данный объект в другом классе, то опять же - этот нужный тип, придется задавать шаблоном, который будет применим еще и к тому классу, в котором хранится данный объект.

А еще, все методы классов в которых мы передаем указатель на базовый, так же будут зависеть от типа, как следствие будут тоже созданы через шаблон. Который нужен то был, совсем для других объектов. Не красиво выходит.
m3g4z0rdEX вне форума Ответить с цитированием
Старый 18.08.2016, 17:59   #7
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,405
По умолчанию

Типа это?

Код:
class A
{
public:
    virtual Base&   GetItem() = 0;
};
class B : public A
{
    std::vector<ChildOfBase>    mVector;
    virtual Base&  GetItem()    { return mVector[0]; }
};
waleri вне форума Ответить с цитированием
Старый 18.08.2016, 18:44   #8
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 673
По умолчанию

Цитата:
Ну вот в вашем примере, выше - да, можем создать объект базового класса, указав с треугольных скобках нужный тип, однако, если я буду хранить данный объект в другом классе, то опять же - этот нужный тип, придется задавать шаблоном, который будет применим еще и к тому классу, в котором хранится данный объект.
С чего вы взяли? Вот, FF не шаблон:
Код:
class A {};
class B: public A {};
class C: public A {};
class D {};
class E: public D {};

struct FF
{
  Arptr_base<A> *arptr1 = {new Arptr<A, B>{20}};  // Так писать нельзя, заворачивать в юник птр или подобное
  Arptr_base<A> *arptr2 = {new Arptr<A, C>{20}};
  Arptr_base<D> *arptr3 = {new Arptr<D, E>{20}};
};
Хотя возможно не понял, что вам надо. В любом случаи - я бы так не писал. Вся эта виртуальность не даст хорошенько заоптимизировать код, добавляет размер, усложняет вызов, а шаблоны - совсем другое дело.
220Volt вне форума Ответить с цитированием
Старый 18.08.2016, 19:10   #9
m3g4z0rdEX
Пользователь
 
Регистрация: 14.10.2015
Сообщений: 17
По умолчанию

"С чего вы взяли? Вот, FF не шаблон:"

Ну это если мы заранее знаем тип. Не спорю. Но в моем случае - тип всегда задает пользователь, когда пишет код. Мягко говоря есть объекты - Итемы, у них есть метод, получить такое то свойство. Итемы хранятся в другой структуре, которая оперирует с ними. Итем могут быть разными - фигуры, сцены и т.п... Только виртуальность задает те пераметры, которые нужны, для того чтобы код работал как надо - т.е пара функций чисто виртуальных. Вот как то так. В страктура что оперирует над ними, хранит целый вектор этих итемов. Что бы все работало верно, приходится да, использовать указатель на базовый класс. Но я решил переделать дизайн и сделал так, чтобы пользователь, переопределяя структуру данных, сам в ней создавал данный массив, а не чтобы он хранился в базовом классе. Т.е можно создать и массив объектов, а не указателей. Главное, чтобы Вирт. Функции работали как надо.

Ну да, виртуальность не дает конечно оптимизации 100%, ибо поиски функций выполняются во время выполнения, но С++ и высоко оптимизированный код - дело, не совсем этичное, как мне кажется. Нужны оптимизации - есть С. И тут же обматерюсь, что в х64 MSVC - нельзя делать ASM вставки, что никак не говорит о 100% оптимизации. Особенно когда речь идет о SIMD.

Последний раз редактировалось m3g4z0rdEX; 18.08.2016 в 19:14.
m3g4z0rdEX вне форума Ответить с цитированием
Старый 18.08.2016, 20:48   #10
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,405
По умолчанию

Цитата:
Сообщение от m3g4z0rdEX Посмотреть сообщение
можно создать и массив объектов, а не указателей.
Массив всегда будет с объектами одного типа - зачем тогда виртуализация?
waleri вне форума Ответить с цитированием
Ответ

           Интенсив по Python: Работа с API и фреймворками 24-26 ИЮНЯ 2022. Знаете Python, но хотите расширить свои навыки?
           Slurm подготовили для вас особенный продукт! Оставить заявку по ссылке - https://slurm.club/3MeqNEk

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Проблемы с vba (проблемы создания макросов) Leojse Microsoft Office Excel 4 26.12.2013 20:09
Вопрос с дизайном Furyon HTML и CSS 9 14.05.2011 09:11
трабл с проектированием БД запчастей автомобильных agent007 Microsoft Office Access 8 12.04.2011 20:27
Решил занятся веб дизайном Zveroboy Свободное общение 5 05.08.2009 01:25