С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.63/8: Рейтинг темы: голосов - 8, средняя оценка - 4.63
1 / 1 / 0
Регистрация: 20.09.2018
Сообщений: 63

Оператор преобразования типа для неконстантной ссылки

23.09.2023, 15:00. Показов 1857. Ответов 52
Метки c++ (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте. Я работаю над большим приложением, задействующим несколько сторонних библиотек. В каждой библиотеке реализован свой класс математического вектора. При этом, структуры и методы из этих библиотек в моем приложении обмениваются данными в виде этих векторов. То есть, я могу получить вектор методом из одной библиотеки, а потом передать его методу в другую библиотеку.
Для того, чтобы каждый раз не преобразовывать один вектор в другой (суть их одна и та же: три компоненты - x, y, z), я сделал класс-адаптер, в котором перегрузил операторы преобразования типа, которые могут возвращать созданные объекты-векторы из обеих библиотек по значению или по константной ссылке, все прекрасно работает.
Теперь появились методы, которые хотят принимать неконстантную ссылку на вектор, и я не совсем понимаю, как мне быть. Мой адаптер выглядит примерно так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//forward declaration
struct Lib1Vector;
struct Lib2Vector;
 
struct MyAdapter
{
    float x;
    float y;
    float z;
private:
    Lib1Vector* lib1Vector;
    Lib2Vector* lib2Vector;
public:
    ...// конструкторы, деструктор
    operator Lib1Vector() const;
    operator Lib2Vector() const;
    operator const Lib1Vector()& const;
    operator const Lib2Vector()& const;
    
}
Если некая функция получит доступ к полю, например, lib1Vector и изменит его значение (по неконстантной ссылке), то поля x,y,z, которые единственные ранее использовались для изменения состояния вектора, будут хранить устаревшие значения. Подскажите, пожалуйста, как мне решить данную проблему. Быть может, сам подход к ней в корне неверен. Спасибо
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
23.09.2023, 15:00
Ответы с готовыми решениями:

Оператор преобразования типа в классах
Допустим, есть три класса: //Фигура class figure; //Дамка class king { public: void step(figure&);

Оператор преобразования типа в char*
Всем привет! Вот у меня есть готовый код для класса Complex #include <iostream> #include <cmath> using namespace std; ...

Оператор динамического преобразования типа возвращает ссылку NULL
Доброго всем времени суток. Пытаюсь разобраться с работой оператора dynamic_cast using namespace std; class parentClass { ...

52
Заблокирован
23.09.2023, 16:41
Лучший ответ Сообщение было отмечено DrOffset как решение

Решение

Так у вас нет приведения к ссылке.
Если типы совместимые, можно попробовать union.
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
42
43
#include <iostream>
 
using namespace std;
 
struct B{
   int val;
};
struct D{
   int val;
};
 
struct A{
   A():x{}, ref{x.b.val}{
      ref = 10;
   } 
   union{
      B b;
      D d;
   } x;
   int &ref;
   operator B&(){
      return x.b;
   };
   operator D&(){
      return x.d;
   };
};
 
void foo(B& b){
   b.val = 100;
}
void bar(D& d){
   d.val = 1000;
}
int main()
{
   A a;
   cout << a.ref << endl;
   foo(a);
   cout << a.ref << endl;
   bar(a);
   cout << a.ref << endl;
}
Добавлено через 3 минуты
Цитата Сообщение от SmallEvil Посмотреть сообщение
int &ref;
Лишь для наглядности, он там не нужен, так как можно использовать поля из объединения.

Добавлено через 2 минуты
C++
1
2
struct A{
   static_assert(sizeof(B)==sizeof(D), "B!=D");
На всякий случай ассерт поставим.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
23.09.2023, 16:45
danascully, кое-какие мысли есть, но для большей ясности хотелось бы получить законченный пример, который иллюстрирует проблему, а именно:
как вы используете адаптер,
как синхронизируете значения адаптера с настоящим вектором,
и т.д. чтобы можно было его у себя скомпилировать, исправить вашу проблему и отдать обратно вам, а вы точно убедились, что решение подходит именно для той ситуации, которую вы имели в виду.
0
1 / 1 / 0
Регистрация: 20.09.2018
Сообщений: 63
24.09.2023, 12:23  [ТС]
Здравствуйте. Отчасти не понял вашу мысль, отчасти, посмотрев на мейн, понял, что это не совсем то, что я хочу. Я хочу, чтобы можно было мой вектор-адаптер подставлять передавать в функции, которые принимают векторы из библиотек по значению и ссылке (конст и не конст). Причем, я хочу чтобы это происходило посредством неявного преобразования типов, чтобы я в классах типы полей-векторов-из-либ сменил на тип моего вектора и не пришлось сильно редачить остальной код, там где эти поля используются
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
24.09.2023, 12:26
Цитата Сообщение от danascully Посмотреть сообщение
это не совсем то, что я хочу.
Ну вот именно поэтому я и написал выше:
Цитата Сообщение от DrOffset Посмотреть сообщение
чтобы можно было его у себя скомпилировать, исправить вашу проблему и отдать обратно вам, а вы точно убедились, что решение подходит именно для той ситуации, которую вы имели в виду.
Законеченный компилируемый пример описываемой ситуации в студию, иначе все гадание рискует стать потерей времени для вас и для отвечающих.
0
1 / 1 / 0
Регистрация: 20.09.2018
Сообщений: 63
24.09.2023, 12:27  [ТС]
В процессе написания!
0
677 / 479 / 216
Регистрация: 06.09.2013
Сообщений: 1,312
24.09.2023, 13:09
Лучший ответ Сообщение было отмечено DrOffset как решение

Решение

Цитата Сообщение от danascully Посмотреть сообщение
Для того, чтобы каждый раз не преобразовывать один вектор в другой
Я бы так делал и не парился. Написал бы пару таких тупых функций:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
namespace type_conversions {
 
template<typename T>
auto convertTo(const cv::Point2d& p) {
    return T(p.x, p.y);        
}
 
template<typename T>
auto convertTo(const QPointF& p) {
    return T(p.x(), p.y());
}
 
}
Сложностей и без того в жизни хватает.
1
1 / 1 / 0
Регистрация: 20.09.2018
Сообщений: 63
24.09.2023, 13:48  [ТС]
Что ж, спустя пару часов тщетных попыток реализовать желаемый класс Adapter я пришел к следующим выводам
1) Оставить у класса Adapter возможность получать и изменять значения полей structure-like сопосбом почти наверняка не получится.
2) Идея создать в классе Adapter поля Vector1 и Vector2, чтобы при вызове оператора приведения по константой ссылке тупо заполнять их необходимыми float значениями, тоже не выгорит, ибо хочется чтобы этот оператор был константным методом.
3) Была идея сделать перечисление, которое будет сохранять, какой тип редактировался последним: float(по умолчанию), Vector1 или Vector2. Если отказаться от идей 1 и 2, то можно в начале каждого метода исходя из значения перечисления понять, какое поле соответствуюет истинному (последнему измененному) значению вектора и работать с ним.
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
struct Vector1
{
    float x = 0.0f;
    float y = 0.0f;
    float z = 0.0f;
 
    static void ValFunc(Vector1 vec1) {};
    static void ConstRefFunc(const Vector1& vec1) {};
    static void NonConstRefFunc(Vector1& vec1) {};
};
 
struct Vector2
{
    float x = 0.0f;
    float y = 0.0f;
    float z = 0.0f;
 
    static void ValFunc(Vector2 vec2_) {};
    static void ConstRefFunc(const Vector2& vec2_) {};
    static void NonConstRefFunc(Vector2& vec2_) {};
};
 
class Adapter
{
    float x = 0.0f;
    float y = 0.0f;
    float z = 0.0f;
 
public:
    Adapter();
    Adapter(float x_, float y_, float z_);
    Adapter(const Vector1& vec1_);
    Adapter(const Vector2& vec2_);
    ~Adapter();
    operator const Vector1& () const;
    operator const Vector2& () const;
    operator Vector1& ();
    operator Vector2& ();
};
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
24.09.2023, 13:55
danascully, просто опишите в коде контракт использования вашего гипотетичесского адаптера.
Например, библиотека 1 принимает вектор1, например заполняет его, далее библиотека2, принимает этот вектор для модификации, но уже как вектор2, при этом изменения должны отразиться и на вектор1.
Типа того
C++
1
2
3
4
5
6
7
8
9
Adapter adp;
lib1FillVector(adp); // lib1FillVector(Vector1& vec);
// adp.x = 1, adp.y = 2
 
lib2ModVector(adp); // lib2ModVector(Vector2& vec);
// adp.x += 1, adp.y += 1
 
Vector1 const& a = adp; // a.x = 2, a.y = 3
Vector2 const& b = adp; // b.x = 2, b.y = 3
Это вам нужно?
0
1 / 1 / 0
Регистрация: 20.09.2018
Сообщений: 63
24.09.2023, 13:58  [ТС]
Да, похоже на то
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
24.09.2023, 14:11
Лучший ответ Сообщение было отмечено danascully как решение

Решение

Цитата Сообщение от danascully Посмотреть сообщение
Да, похоже на то
Кликните здесь для просмотра всего текста

https://wandbox.org/permlink/GxEgEF3Y5LM7tMyd
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <iostream>
 
struct Vector1
{
    float x;
    float y;
    float z;
};
 
struct Vector2
{
    float x;
    float y;
    float z;
};
 
class Adapter {
private:
    union 
    {
        Vector1 type1;
        Vector2 type2;  
    };
public:
    float& x;
    float& y;
 
    Adapter() : type1(), x(type1.x), y(type1.y)
    {}
    Adapter(Adapter const& other) : Adapter()
    {
        x = other.x;
        y = other.y;
    }
    Adapter& operator=(Adapter const& other)
    {
        if(&other != this) {
            x = other.x;
            y = other.y;
        }
        return *this;
    }
 
    operator Vector1&() 
    {
        return type1;        
    }
    operator Vector2&() 
    {
        return type2;        
    }
};
 
void lib1FillVector(Vector1& vec) 
{
    vec.x = 1;
    vec.y = 2;
}
 
void lib2ModVector(Vector2& vec)
{
    vec.x += 1;
    vec.y += 1;
}
 
int main() 
{
    Adapter adp;
    adp.x = 0;
    adp.y = 0;
 
    lib1FillVector(adp);
 
    std::cout << adp.x << ' ' << adp.y << std::endl;
    Vector2 const& vec2 = adp;
    std::cout << vec2.x << ' ' << vec2.y << std::endl;
    
    lib2ModVector(adp);
    
    std::cout << adp.x << ' ' << adp.y << std::endl;
    Vector1 const& vec1 = adp;
    std::cout << vec1.x << ' ' << vec1.y << std::endl;
}


Добавлено через 2 минуты
Vector1 и Vector2 должны быть layout-compatible (типы полей и настройки выравнивания для них должны быть одинаковыми), иначе работать не будет.
2
Заблокирован
24.09.2023, 14:19
DrOffset, хм, я ведь ту же самую идею предложил.
Жаль что у ТС не хватило сил её доделать под себя.
1
1 / 1 / 0
Регистрация: 20.09.2018
Сообщений: 63
24.09.2023, 14:20  [ТС]
Не понимаю, как при вызове оператора
C++
1
operator Vector2&()
поле type2 получает значения x, y
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
24.09.2023, 14:25
Цитата Сообщение от SmallEvil Посмотреть сообщение
хм, я ведь ту же самую идею предложил.
Конечно, никто этого не отрицает.

Добавлено через 1 минуту
Цитата Сообщение от danascully Посмотреть сообщение
Не понимаю, как при вызове оператора
Union.

Добавлено через 2 минуты
Цитата Сообщение от SmallEvil Посмотреть сообщение
Жаль что у ТС не хватило сил её доделать под себя.
Я бы сказал, что не хватило нормального описания задачи, чтобы вы или я не гадали, а ТС имел критерии проверки подходит или нет. По этой причине я не стал спешить предлагать union, хотя это самоочевидное решение в этой ситуации. ТС оказался банально не готов к вашему решению, потому что никаких критериев проверки им озвучено не было.
Хорошо заданный вопрос - это половина ответа.
3
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
24.09.2023, 14:33
Цитата Сообщение от danascully Посмотреть сообщение
Если некая функция получит доступ к полю, например, lib1Vector и изменит его значение (по неконстантной ссылке), то поля x,y,z, которые единственные ранее использовались для изменения состояния вектора, будут хранить устаревшие значения.
danascully, если вы сохраняете указатели на вектора состоящие из x,y,z то вам нет нужды хранить x,y,z отдельно. Это приводит к необходимости их апдейта и не даёт ни чего взамен.
Ваш default конструктор заделетьте, в каждом конструкторе принимающем ссылку на соответствующий вектор, инициализируйте его указатель, а другой установите в nullptr. В операторе преобразования к соответствующему вектору верните разыменованный указатель на него, если он не равен nullptr - иначе - исключение. Для выяснения, какой вектор валиден придётся написать метод возвращающий элемент перечисления говорящий о том кто есть ху. Такое перечисление нужно написать. Это плата за желание возвращать ссылку на разные типы при преобразовании. Или ловите и обрабатывайте исключение, если не угадали)
Может я не понял вопроса, но если понял, то я так увидел решение.
1
677 / 479 / 216
Регистрация: 06.09.2013
Сообщений: 1,312
24.09.2023, 14:46
DrOffset, а зачем ссылки x, y в классе адаптера? Тем более что они привязываются к ссылкам на члены одного из объектов, которые в общем случае могут не быть доступны. Можно же просто добавить get и set методы в класс адаптера, выбирающие их из какого-нибудь типа объединения. Да и сэкономить десяток байтов заодно.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
24.09.2023, 14:48
Цитата Сообщение от woldemas Посмотреть сообщение
а зачем ссылки на x, y в классе адаптера?
ТС захотел иметь такой доступ, вот я и сделал.

Цитата Сообщение от woldemas Посмотреть сообщение
которые в общем случае могут не быть доступны.
Здесь не общий случай. Здесь частный случай layout-compatible векторов.

Цитата Сообщение от woldemas Посмотреть сообщение
Можно же просто добавить get и set методы в класс адаптера, выбирающие их из какого-нибудь типа объединения.
Можно, если ТС это устроит. Пока что он дал понять, что нет:
Цитата Сообщение от danascully Посмотреть сообщение
у класса Adapter возможность получать и изменять значения полей structure-like сопосбом
0
1 / 1 / 0
Регистрация: 20.09.2018
Сообщений: 63
24.09.2023, 14:50  [ТС]
Занимался проверкой того, что мои вектора layout compatible.
В итоге мой Vector1=DirectX::SimpleMath::Vector3, Vector2=physx::PxVec3. Создание юниона как у вас в коде показало, что все работает. Буду имплементировать.
Скажу про свое приложение. Это игровой движок. адаптер мне нужен, чтобы прокидывать данные из редактора сцены (DirectX) в физику (physx), и из симуляции физики в рендер-пайплайн (DirectX). Виноват, что сразу не поянсил. Большое спасибо всем знатокам!
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
24.09.2023, 14:51
Цитата Сообщение от danascully Посмотреть сообщение
Занимался проверкой того, что мои вектора layout compatible.
https://en.cppreference.com/w/... compatible
0
1 / 1 / 0
Регистрация: 20.09.2018
Сообщений: 63
24.09.2023, 14:52  [ТС]
У моих векторов есть доступ к полям x,y,z, так что и у адаптера должен быть.

Добавлено через 25 секунд
К сожалению, проект на с++17, так что is_layout_compatible не смог применить
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
24.09.2023, 14:52
Помогаю со студенческими работами здесь

Определить оператор преобразования типов из типа дробь в тип double
Добрый вечер, Я только начал обучаться на факультет С#; Такая задачка, я создал класс дробь с двумя параметрами RationalNumbers(int...

Странный порядок вызова конструкторов и передача временного обьекта в функцию в качестве неконстантной ссылки
Есть код //g++ 5.4.0 #include &lt;iostream&gt; struct foo { foo(int){std::cout &lt;&lt; &quot;int ctor&quot; &lt;&lt; std::endl;} foo()...

Оператор преобразования типа и его эквивалентные замены, поиск строки в текстовом файле , содержащей заданный
Господа, был бы очень признателен если бы кто то помог ответить на вапросы http://cs616225.vk.me/v616225102/122f8/5kAaFEGoDn0.jpg

Оператор new для возвращения ссылки
Здравствуйте Увидел такой код впервые и мне интересно: для чего он нужен? T* instance = freeList.Pop(); return new...

Функция для преобразования из типа float в char
Всем привет! Если у кого-то есть возможность подсказать, как из float преобразовать число с плавающей точкой (В моем случае 4,2) в char,...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути
Programma_Boinc 01.01.2026
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути Сочетание глобально распределённой вычислительной мощности и инновационных. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru