Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.90/40: Рейтинг темы: голосов - 40, средняя оценка - 4.90
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491

Предупреждение при создании динамической библиотеки

11.01.2021, 19:19. Показов 9196. Ответов 56
Метки c++ (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый вечер,

У меня мало опыта создания динамических библиотек.
Я пытаюсь написать динамическую библиотеку, в качестве системы сборки использую используя CMake.

Моя динамическая библиотека задействует Eigen библиотеку и HighFive. Это хэдэр онли библиотеки (но вторая задействует HDF5 библиотеку, которая компилируется отдельно).

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "../export/myclass_export.h"
#include "../core/core.h"
 
#include <Eigen/Dense>
 
#include <optional>
 
class MYCLASS_EXPORT MyClass
{
  MyClass();
 
private:
  HighFive::Group devCurveGroup;    // warning: C4251: 'MyClass::devCurveGroup': class 'HighFive::Group' needs to have dll-interface to be used by clients of class 'MyClass' 
  HighFive::DataSet devDataD;    // warning: C4251: 'MyClass::devCurveGroup': class 'HighFive::Group' needs to have dll-interface to be used by clients of class 'MyClass' 
};
Но получаю предупреждения:
warning: C4251: 'MyClass::devCurveGroup': class 'HighFive::Group' needs to have dll-interface

Я погуглил и насколько я понял, суть заключается в следующем:
внутри класса MyClass я использую шаблонные классы стандартной библиотеки (вероятно внутри HighFive::Group и HighFive:ataSet), которые я пытаюсь экспортировать (так как экспортирую весь класс MyClass ). Шаблонные классы (и функции) в неявном виде (без явной инициализации класса/функции) нельзя экспортировать, отсюда и предупреждение насколько я понимаю. И в результате, если я скомпилирую свой класс MyClass в библиотеку с этим предупреждением, то эту скомпилированную динамическую библиотеку можно использовать только приложениями, собранными моим же компилятором (у меня MSVC 2019 x64) и нельзя путать Release/Debug версии библиотеки.

Верно ли это высказывание?
Вообще я думал что ни статические, ни динамические библиотеки, собранные компилятором А, не получается использовать с компилятором Б, и нельзя смешивать релиз/дебаг версии библиотек, иначе получаешь ошибки на этапе линковки.

class_export.h генерируется с помощью CMake функции:
Code
1
2
3
4
generate_export_header(
  ${libname}
  EXPORT_FILE_NAME ${CMAKE_CURRENT_SOURCE_DIR}/${libname}_export.h
  )
содержимое class_export.h:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifndef MYCLASS_EXPORT_H
#define MYCLASS_EXPORT_H
 
#ifdef MYCLASS_STATIC_DEFINE
#  define MYCLASS_EXPORT
#  define MYCLASS_NO_EXPORT
#else
#  ifndef MYCLASS_EXPORT
#    ifdef MYCLASS_EXPORTS
        /* We are building this library */
#      define MYCLASS_EXPORT __declspec(dllexport)
#    else
        /* We are using this library */
#      define MYCLASS_EXPORT __declspec(dllimport)
#    endif
#  endif
 
#  ifndef MYCLASS_NO_EXPORT
#    define MYCLASS_NO_EXPORT 
#  endif
#endif
 
#ifndef MYCLASS_DEPRECATED
#  define MYCLASS_DEPRECATED __declspec(deprecated)
#endif
 
#ifndef MYCLASS_DEPRECATED_EXPORT
#  define MYCLASS_DEPRECATED_EXPORT MYCLASS_EXPORT MYCLASS_DEPRECATED
#endif
 
#ifndef MYCLASS_DEPRECATED_NO_EXPORT
#  define MYCLASS_DEPRECATED_NO_EXPORT MYCLASS_NO_EXPORT MYCLASS_DEPRECATED
#endif
 
#if 0 /* DEFINE_NO_DEPRECATED */
#  ifndef MYCLASS_NO_DEPRECATED
#    define MYCLASS_NO_DEPRECATED
#  endif
#endif
 
#endif /* MYCLASS_EXPORT_H */
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
11.01.2021, 19:19
Ответы с готовыми решениями:

Вызов функции одной динамической библиотеки из другой динамической библиотеки
Добрый день! Помогите пожалуйста разобраться со следующим вопросом. Возможно ли из одной библиотеки передать параметры для...

Ошибка при подключении динамической библиотеки
Всем привет! Помогите пожалуйста разобраться со следующим: Установил библиотеку cURL, раскидав либы и длл файлы по нужным папкам....

Утечка памяти при создании динамической переменной класса
Никак не могу исправить проблему утечки памяти при создании динамической переменной класса class Ship { private: int maxHeight; ...

56
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
16.01.2021, 17:55
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
Как видите, идея использовать приватный конструктор у меня задействована, и по сути std::optional<> можно заменить на умный указатель, и тогда хочется использовать подход, основанный на интерфейсах. Но я использую сторонние шаблонные библиотеки (хэдэр онли), это Eigen и HighFive (оболочка для hdf5 чистой СИ библиотеки). Становится непонятным как мне экспортировать классы этих библиотек Eigen::MatrixXd и HighFive::Group (или DataSet).
Если экспортировать мой класс Surf, то я вижу только способ использования указанных сторонних классов (Eigen::MatrixXd и HighFive::Group) только как указателей вместо объектов, но делать этого очень не хочется, так как становится очень непривычно использовать эту библиотеку, для тех, кто работает с матрицами Eigen и HighFive.
Второй вариант это забыть про бинарную совместимость.
Просто обеспечьте нормальный, простой способ сборки вашей библиотеки под разные компиляторы и платформы, например с помощью cmake. Напишите инструкцию как это делать. У вас будет требование, что библиотека нуждается в сборке под каждый из используемых пользователем компиляторов. Это нормально, это очень частое явление.

Добавлено через 6 минут
Kerim_Geophysic, В этом случае вам нужно будет:
1) сделать хороший, непротиворечивый интерфейс к библиотеке;
2) сторонние библиотеки лучше из интерфейса убрать. В С++ есть несколько подходов как это обеспечить (например PIMPL);
3) классы можно оставить, но тщательно изучить особенности экспорта классов в каждом из поддерживаемых вами компиляторов;
4) Если вы собрались передавать сложные объекты, использующие динамическую память, через границу DLL, то продумать варианты использования библиотеки времени исполнения С++ в вашей DLL.

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

Добавлено через 4 минуты
Kerim_Geophysic, вариант, когда одна DLL подходит всюду, конечно, самый лучший. Но его не всегда "бесплатно" можно получить. Т.е. нужно смотреть по ситуации, чем мы платим и что получаем взамен. Может так получиться, что цена в виде понижения выразительности, ограничения возможностей или в слишком большом количестве второстепенной работы может перекрыть пользу от универсальности библиотеки.
Советую тщательно изучить уже существующие решения, на github есть множество примеров разных подходов. Уделите день-два на анализ.
2
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,554
20.01.2021, 19:10
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
универсальны только указатели, которые корректно преобразуются при помощи reinterpret_cast. В частности, это функции.
спасибо за ответ - такое даже между языками работает - из C++ в C# - всё в .NET - хоть в том случае и, вероятно, с одним компилятором (если только sqlite3 не dll, собранная др. компилятором)
0
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,554
03.02.2021, 16:53
Использование интерфейсов при работе с DLL - кратко, локанично и по утверждению автора
Этой информации вполне достаточно, чтобы вы почувствовали все удобство использования интерфейсов.
Добавлено через 2 часа 44 минуты
========
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
В частности, static_cast и dynamic_cast могут возвращать указатель, отличный от переданного.
... совсем забыла... мы же результат из dll возвращаем в тот же указатель, с которым пришли в эту dll от клиента... значит, ваш ответ по dynamic_cast становится очень даже понятным...
но мне всё равно кажется, что если мы в абстрактном классе сделаем виртуальные методы с разными названиями для разных наследников - то хоть таким способом сможем реализовать полиморфизм в dll (ТС вроде писал, что хочет в dll'е обрабатывать разные файлы)... если кастить от родителя к потомкам не придётся - то и нормально... имхо?.. а от потомков к предкам и так кастится без лишних классов...
касательно компиляторов - всё упирается в name-mangling, и чтобы этого избежать оборачивается в extern "c"... но можно писать dll и на чисто С (поняла, почему, например, sqlite3 весь на С в source_code)... тогда, конечно, перегрузкой, как вариантом реализации полиморфизма, не воспользоваться - но на C, наверно, есть др. рабочие ходы или просто немного др. архитектуру сделать для этих целей?.. имхо...
в любом случае, для ТСа вариант перегрузки в классе, может ли подойти?.. чтобы без этих его optional... или std::variant ?.. - хотя тут (в любом C++), видимо всё опять упрётся в разность компиляторов, если таковая будет иметься для dll и для клиента... и в name-mangling...
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Скорее всего, твоя dll разъедется при первом же обновлении/изменении компилятора.
но в конце-то концов и перекомпилировать можно dll'ю... хотя глупо делать dll, чтобы её потом перекомпилировать постоянно... согласна...
! в связи с этим мне показалось, что dll'и на С++ вообще НЕ очень хорошая идея с учётом этого name-mangling от разных компиляторов и даже версий одного компилятора... на С надёжнее писать dll'и... имхо?..
(ну нет полиморфизма на С - и не надо, - загрузиться в нужную функцию dll'и ещё на стороне клиента [в смысле создать указатель на нужную функцию] и то нормально)...
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
универсальны только указатели, которые корректно преобразуются при помощи reinterpret_cast. В частности, это функции.
это, видимо, если dll компилировалась др. компилятором...
действительно, её удобство появится лишь если она сможет быть подключена к клиенту с любого компилятора... иначе смысла нет так заворачивать отдельный модуль в подарочную упаковку, чтобы подарить клиенту в run'time'e... всё равно придётся постоянно перезаворачивать...
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Т.е. смысла в ней не будет никакого, можешь даже не заморачиваться. Оставь только статическую линковку.
Добавлено через 12 минут
ну или оборачивать dll в COM, как уже звучало
1
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
03.02.2021, 17:12
Цитата Сообщение от JeyCi Посмотреть сообщение
но мне всё равно кажется, что если мы в абстрактном классе сделаем виртуальные методы с разными названиями для разных наследников - то хоть таким способом сможем реализовать полиморфизм в dll (ТС вроде писал, что хочет в dll'е обрабатывать разные файлы)... если кастить от родителя к потомкам не придётся - то и нормально... имхо?.. а от потомков к предкам и так кастится без лишних классов...
Хотя, снаружи длл static_cast можно будет сделать только к интерфейсам, которые наследуются один от другого. В этом случае он вроде должен всегда нормально отрабатывать, там указатели на предка и наследника всегда будут численно равны, смещение добавлять не нужно.
Т.е. можно не заморачиваться, static_cast нормально будет отрабатывать.
1
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,554
03.02.2021, 19:16
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
там указатели на предка и наследника всегда будут численно равны, смещение добавлять не нужно.
кажется, начинаю понимать vtbl (таблицу виртуальных методов)... Спасибо!
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
снаружи длл static_cast можно будет сделать только к интерфейсам, которые наследуются один от другого
значит последовательно, а не деревом... - однако вариант... может std::variant ещё лучший вариант реализации полиморфизма внутри dll ? - вроде vtbl вообще не нужна будет... имхо?

Добавлено через 27 минут
p.s.
для инфо - Основы COM-pdf (хотя в Borand казалось, что это проще - Borland C++ Builder 6. Холингворт)

Добавлено через 34 минуты
p.p.s.
Цитата Сообщение от JeyCi Посмотреть сообщение
(таблицу виртуальных методов)...
не, всё-таки там НЕ смещение (по линку), как в обыкновенном наследовании vbptr, а в виртуальном наследовании - адреса функций в vfptr... пусть ТС сам разбирается... я всё-равно тестить пока не буду такое (время однако)... но интерес останется на потом... всем, спасибо, что ход логической мысли корректируете

Добавлено через 5 минут
p.p.p.s.
и regsvr32 для com сделать как-то проще, чем везде с собой носить эту dll (или разве что запихнуть её в Windows S*S)...- по линку отсюда... имхо
0
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
04.08.2021, 03:21  [ТС]
oleg-m1973, доброго времени,

Я написал свою библиотеку в виде интерфейсов с полиморфизмом. Руководствовался советами, полученными в этой теме, в частности этим постом

В упрощенном виде есть у меня такой интерфейс h5base.h (на самом деле это базовый интерфейс и далее от него наследуются интерфейсы, но всю цепочку сложно приводить):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class H5Base
{
protected:
  virtual ~H5Base() = default;
 
public:
  virtual void Delete() = 0;
};
 
 
struct ObjectDeleter
{
  void operator()(H5Base * ptr) const
  {
    ptr->Delete();
  }
};
Вот такая его реализация h5baseimpl.h (класс H5BaseImpl - impl -от слова имплиментайшн):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "h5base.h"
 
class H5BaseImpl : public virtual H5Base
{
protected:
  explicit H5BaseImpl(const h5gt::File &h5File) : h5File(h5File){};
  virtual ~H5BaseImpl() = default;
 
public:
  virtual void Delete() override {delete this;};
 
protected:
  h5gt::File h5File;
 
friend H5Base* openBase(h5gt::File h5File);
};
 
H5Base* openBase(const h5gt::File &h5File)){
  return new H5BaseImpl(h5File);
};
 
using H5Base_ptr = std::unique_ptr<H5Base, ObjectDeleter>;
Теперь я рассматриваю два варианта работы с этим интерфейсом: через сырой указатель и через уникальный умный указатель.

Я заметил, что если я пытаюсь удалить сырой указатель то он удаляется нормально:
C++
1
2
3
h5gt::File file("D:/tmp/test.h5");
H5Base* base = openBase(file);
base->Delete(); // все ок
Но если я пытаюсь сделать то же самое с умным указателем:
C++
1
2
3
h5gt::File file("D:/tmp/test.h5");
H5Base_ptr base = H5Base_ptr(openBase(file));
base->Delete(); // получаю исключение
выскакивает исключение:
unknown file: error: SEH exception with code 0xc0000005 thrown in the test body.

Интуиция подсказывает, что в данном случае так и должно быть, но я не понимаю что не так.

Если возможно, прокомментируйте пожалуйста происходящее
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
04.08.2021, 07:50
Kerim_Geophysic, просто не надо руками вызывать Delete.

Добавлено через 2 минуты
Если нужно удалить объект до окончания времени жизни умного указателя, используйте base.reset()
1
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
05.08.2021, 00:39
Kerim_Geophysic, сделай вот так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct ObjectDeleter
{
   template <typename T>
   void operator()(T *ptr) const
   {
      ptr->Delete();
   }
};
 
class H5Base
{
friend ObjectDeleter;
protected:
   ~H5Base() = default;
   virtual void Delete() = 0;
public:
 
};
 
using H5Base_ptr = std::unique_ptr<H5Base, ObjectDeleter>;
тогда будет гораздо тяжелее делать такие ошибки

И - виртуальный деструктор для H5Base и виртуальное наследование для H5BaseImpl не нужны
1
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
05.08.2021, 01:35  [ТС]
oleg-m1973, спасибо за совет
Завтра попробую, потестирую

П.С. вообще виртуальное наследования я делал для решения задач множественного наследования. Сейчас точно не помню как там множественное наследование работает, но в реальности у меня структура примерно такая как показана на картинке в приложении (так как я ранее пытался упростить схему и изменял названия, и если у вас вдруг возникнут вопросы которые взрывают мозг то на всякий случай вот ссылка на мою библиотеку )
Миниатюры
Предупреждение при создании динамической библиотеки  
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
05.08.2021, 12:40
Лучший ответ Сообщение было отмечено Kerim_Geophysic как решение

Решение

Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
Сейчас точно не помню как там множественное наследование работает, но в реальности у меня структура примерно такая как показана на картинке в приложении
Насколько я понимаю, здесь тебе не виртуальное наследование нужно, а шаблоны. Классы ...Impl должны быть шаблонными
C++
1
2
3
4
5
6
7
template <typename TBase = H5Base>
class H5BaseImpl: public TBase {};
 
template <typename TBase = H5BaseObject>
class H5BaseObjectImpl: public H5BaseImpl<TBase> {};
 
class H5SurfImpl: public H5BaseObjectImpl<H5Surf> {};
1
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
05.08.2021, 15:03  [ТС]
oleg-m1973,
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
тогда будет гораздо тяжелее делать такие ошибки
Сейчас пробую ваши рекомендации, и возник вопрос: если у меня все классы так или иначе наследуются от H5Base, нужно ли делать оператор ObjectDeleter:: () шаблонным?
Например в деструктор класса H5SurfImpl я добавил:
C++
1
2
3
virtual ~H5SurfImpl() {std::cout << "SURF_DESTR" << std::endl;};
 
using H5Surf_ptr = std::unique_ptr<H5Surf, ObjectDeleter>;
и затестил с НЕ шаблонным делитером.
Оказалось, что при разрушении объекта типа H5Surf_ptr как и положено появляется надпись SURF_DESTR.
Просто не очень хочу делать ObjectDeleter шаблоном, так как немного больше кода придется писать конвертируя этот шаблон в питон с помощью pybind11 (но если это необходимо, то в принципе проблем возникнуть не должно с пибайдом).



Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Насколько я понимаю, здесь тебе не виртуальное наследование нужно, а шаблоны. Классы ...Impl должны быть шаблонными
По моему так у меня не получится.
Классы H5Base и H5BaseImpl родоначальники иерархии и H5Base ни от кого не наследуются, а H5BaseImpl наследуется только от абстрактного (или интерфейса, не знаю как правильно назвать) класса H5Base.
Абстрактный H5BaseObject наследуется от абстрактного H5Base, но его реализация H5BaseObjectImpl включает также в себя реализацию H5BaseImpl и естественно добавляет новые методы, задекларированные в H5BaseObject. Ну и так далее с другими классами.
Мне кажется тут множественное наследование у меня имеет место быть (до этого я никогда множественное наследование не использовал, это первый опыт)
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
05.08.2021, 17:25
Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
Сейчас пробую ваши рекомендации, и возник вопрос: если у меня все классы так или иначе наследуются от H5Base, нужно ли делать оператор ObjectDeleter:: () шаблонным?
Я его сделал шаблонным, чтобы объявить ObjectDeleter перед классом H5Base. Можешь сделать его нешаблонным, там без разницы

Добавлено через 3 минуты
Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
По моему так у меня не получится.
В смысле, не получится? Я ж тебе вроде показал как.
Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
Мне кажется тут множественное наследование у меня имеет место быть (до этого я никогда множественное наследование не использовал, это первый опыт)
Если вертикальные стрелочки это наследование, а горизонтальные - это реализация, то никакое множественное наследование здесь не нужно
0
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
06.08.2021, 20:52  [ТС]
oleg-m1973,
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
В смысле, не получится? Я ж тебе вроде показал как.
Только сейчас дошло как ваш пример с шаблонами работает. Спасибо

Мне интересно это вы на опыте такое решение с шаблонами предложили, или сходу сообразили?

На данный момент у моя библиотека разделена на файлы заголовки (.h) и реализации (.cxx).
Если я заменю множественное наследование шаблонами то придется пару часов на это потратить. Вот я думаю, в чем будет заключаться разница (не плане красоты кода, или внешнего оформления, а в плане работы с классами) между шаблонным подходом и нынешним с множественным наследованием? Например будет ли разница в применении dynamic_cast<>() для кастинга наследников в родителей и наоборот?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
06.08.2021, 20:57
Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
Мне интересно это вы на опыте такое решение с шаблонами предложили, или сходу сообразили?
Такой подход используется с тех пор, как появились шаблоны. С прошлого века.

Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
Например будет ли разница в применении dynamic_cast<>() для кастинга наследников в родителей и наоборот?
Постарайся никогда не использовать dynamic_cast. Да и static_cast, по возможности, тоже. Не нужно кастить родителей к наследникам без самой крайней необходимости.
1
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
02.01.2022, 19:38  [ТС]
oleg-m1973, добрый вечер, с Новым Годом!

Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Насколько я понимаю, здесь тебе не виртуальное наследование нужно, а шаблоны. Классы ...Impl должны быть шаблонными
Делаю как вы сказали:

C++
1
2
3
4
5
6
7
template <typename TBase = H5Base>
class H5BaseImpl: public TBase {};
 
template <typename TBase = H5BaseObject>
class H5BaseObjectImpl: public H5BaseImpl<TBase> {};
 
class H5MapImpl: public H5BaseObjectImpl<H5Map> {};
Ну и есть соответствующие классы с которыми непосредственно работает юзер:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class H5Base
{
protected:
  virtual ~H5Base() = default;
 
public:
  virtual H5Base* clone() = 0;
  virtual void Delete() = 0;
};
 
class H5BaseObject : public H5Base
{
protected:
  virtual ~H5BaseObject() = default;
};
 
class H5Map : public H5BaseObject
{
protected:
  virtual ~H5Map() = default;
};
и не могу понять как мне реализовать метод H5Base* clone() для H5Map (ну и других наследников H5BaseObject)? То есть понятно что я могу написать override внутри каждого класса ...Impl (например H5MapImpl), но хотелось бы видеть решение задачи в следующем виде:

C++
1
2
3
4
5
template <typename TBase>
H5Base* H5BaseObjectImpl<TBase>::clone()
{
  return new H5BaseObjectImpl<TBase>(h5File); // получаю ошибку
}
Но получаю в ошибку компилятора:
error: allocating an object of abstract class type 'H5BaseObjectImpl<H5Map>'

Суть ошибки понятна, но реализация для H5BaseObject работает нормально:
C++
1
2
3
4
5
template <>
H5Base* H5BaseObjectImpl<H5BaseObject>::clone()
{
  return new H5BaseObjectImpl<H5BaseObject>(h5File);
}
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
03.01.2022, 20:35
Лучший ответ Сообщение было отмечено Kerim_Geophysic как решение

Решение

Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
и не могу понять как мне реализовать метод H5Base* clone() для H5Map (ну и других наследников H5BaseObject)? То есть понятно что я могу написать override внутри каждого класса ...Impl (например H5MapImpl),
Вот как раз метод clone тебе придётся реализовывать в каждом из классов ...Impl. Потому что он уникален для каждого из конечных классов. Обобщённый виртуальный метод сделать не получится по-определению.
Но он, вроде простой, в чём проблема? Иначе придётся сильно усложнять код, на мой взгляд, оно того не стоит.
1
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
03.01.2022, 21:07  [ТС]
oleg-m1973, понял, буду знать, спасибо
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
03.01.2022, 21:07

Синтаксическая ошибка при создании библиотеки: __declspec(dllimport)
Итак, братья-кролики , создаю я дллку с таким вот кодом , а мне ошибочку все время не понятную выбивает. Подсобите с решением. #ifndef...

Компилятор требует функцию main при создании библиотеки
Я создал проект на плюсах. В настройках проекта в Configuration Properties -&gt; General -&gt; Configuration Type выбрал Static Library (.lib) ....

Любимый Visual Studio не хочет поспособствовать мне в создании библиотеки(статической и динамической)
Уважаемые программисты, если вы дружите с этой прекрасной средой разработки, то прошу вас обосновать, как мне найти данное окно, если при...

Ошибка преобразования при сборке динамической библиотеки
При сборке программы с динамической библиотекой позднего связывания вылазит ошибка: Пробовал как-нибудь преобразовать к одному типу, но не...

Зачем при создании библиотеки создавать два файла (.h и.cpp)
Приветствую. Решил научиться писать часто используемые классы в ДЛЛ . На МСДН все понятно расписано . Однако возникли вопросы : 1.Зачем...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
57
Ответ Создать тему
Новые блоги и статьи
Книги по геймдизайну, левел-дизайну, игровым механикам и проектированию игрового опыта
8Observer8 08.11.2026
Содержание блога | English Version 1. 2003 - 06 - Designing Virtual Worlds (1st Edition) Автор: Richard A. Bartle | Объем: 768 стр. Ссылки: Amazon . . .
Родители токсичные абьюзеры по отношению к своим детям ругают их оскорбляют не любят
zorxor 08.11.2026
Жить в атмосфере постоянных оскорблений, критики и холодности со стороны родителей — это тяжелое и болезненное испытание, которое оставляет глубокие эмоциональные раны. Токсичное и абьюзивное. . .
Как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Ответ от Джемени ИИ.
zorxor 08.11.2026
Джемени, как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Многие люди, возвращаясь домой, сразу переодеваются в максимально свободную одежду или вовсе предпочитают. . .
Паттерн очереди действий/команд (Action / Command Queue). Система очереди действий и кат-сцен с SDL3 Callbacks, cglm и OpenGL
8Observer8 07.11.2026
Содержание блога | English Version Руководство для начинающих по реализации паттерна очереди действий/ команд (Action / Command Queue) на C++ (C++20) с использованием официального SDL3 Callbacks. . .
Проверка полного ФИО в типовом справочнике
Maks 07.11.2026
Решение реализовано в конфигурации КА2, на примере справочника "КонтактныеЛицаПартнеров". Задача: Запрет инициалов. Не допускаеть использование сокращений вида "И. И. ", "И. И. ", "И И" и. . .
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . . Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
Красочные поля с номером страницы svg+background-image
russiannick 04.11.2026
Красочные поля с номером страницы не менее важны чем в эпоху бумажных книг. Посему спешу представить почтеннейшей публике этот важный инструмент который эти поля и формирует. В процессе разработки. . .
Вступаем в новую фазу генерации favicons, векторную.
russiannick 02.11.2026
Теперь нет нужды скрывать что используется простой svg. Исходный код изображения помещаем в поле и жмем кнопку. Исходник преобразуется в вид корректный для помещения в favicon или в url(). Нажатие. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru