Информация об изменениях

Сообщение Re[2]: Не компилируется Qt-проект от 31.08.2022 23:41

Изменено 31.08.2022 23:45 AleksandrN

Re[2]: Не компилируется Qt-проект
Здравствуйте, RussianFellow, Вы писали:

RF>Я убрал библиотеку libpq.lib из моего проекта и я закомментировал весь код, связанный с работой с базами данных (разбираться с этим я буду потом).

RF>После небольших изменений в файлах 3dvecmat.h и 3dvecmat.cpp -- файлы, предназначенные для работы с трехмерными векторами и трехмерными матрицами -- у меня теперь программа компилируется (собирается) и запускается.
RF>В связи с этим у меня к вам, уважаемые коллеги, вопрос: не могли бы вы посмотреть код этих файлов 3dvecmat.h и 3dvecmat.cpp и сказать, всё ли правильно в этих файлах?

RF>Файл 3dvecmat.h :


RF>
RF>    T3DVector& operator= (T3DVector v);
RF>    T3DVector& operator+=(T3DVector v);
RF>    T3DVector& operator-=(T3DVector v);
RF>    T3DVector& operator*=(T3DVector v);
RF>


Лучше
    T3DVector& operator= (const T3DVector &v);
    T3DVector& operator+=(const T3DVector &v);
    T3DVector& operator-=(const T3DVector &v);
    T3DVector& operator*=(const T3DVector &v);


Что бы не вызывать лишний раз конструктор копии при вызове операторов.



RF>Файл 3dvecmat.cpp :


RF>
RF>    LDouble& T3DVector::operator[](int i){return ((LDouble*)&x)[i-1];};
RF>


LDouble это что? typedef для double?
В объявлении класса LDouble x,y,z; и класс попадает под определение POD-класса. Но если в будущем в классе что-то изменится или код будет перенесён на другую архитектуру, то не факт, что x,y,z будут размещены в памяти друг за другом подряд, без пропусков. Ещё нет проверки на то, что i лежит в пределах 0..2.

Лучше заменить на что то вроде
    // Вместо x,y,z.
    std::array<LDouble, 3>    coor;
    // И добавить константы для обращения к координатам x,y,z по индексу.
    enum COOR : size_t
    {
        X = 0,
        Y,
        Z
    };
    // И сделать operator[]
    inline LDouble& T3DVector::operator[](COOR i){ return coor[i]; };


или на
    LDouble x,y,z;
    
    enum COOR
    {
        X = 0,
        Y,
        Z
    };
    // И сделать operator[]
    inline LDouble& T3DVector::operator[](int i)
    {
        switch(i)
        {
            case X: return x;
            case Y: return y;
            case Z: return z;
            default: throw std::invalid_argument(std::string("Invalid index ") + std::to_string(i) + " at T3DVector::operator[]");
        }
    };
    // И там, где в классе надо обращаться к координатам, писать coor[X], coor[Y], coor[Z]



RF>#define swap(X,Y)  tmp=(X),(X)=(Y),(Y)=tmp
RF>      swap(a[0][1],a[1][0]);
RF>      swap(a[0][2],a[2][0]);
RF>      swap(a[1][2],a[2][1]);
RF>     return *this;
RF>#undef swap

Зачем делать свой swap, если ещё с C++11 есть std::swap?

RF>            throw 777;

Что такое 777? Если какой-нибудь код ошибки, то лучше магические числа заменить константами.

    LDouble a[3][3];
    ...
    T3DVector& T3DMatrix::operator[](int i) { return *(T3DVector*)a[3*(i-1)];}


a объявлена как массив, а потом адрес одного из элементов массива приводится к указателю на класс??? Работает только потому, что это POD-класс, но это потенциальный источник больших проблем. И что будет, если i будет равно 0?
Переделать на std::array
    std::array<T3DVector, 3> a;
    ...
    inline T3DVector& T3DMatrix::operator[](size_t i) { return a[i];}
Re[2]: Не компилируется Qt-проект
Здравствуйте, RussianFellow, Вы писали:

RF>Я убрал библиотеку libpq.lib из моего проекта и я закомментировал весь код, связанный с работой с базами данных (разбираться с этим я буду потом).

RF>После небольших изменений в файлах 3dvecmat.h и 3dvecmat.cpp -- файлы, предназначенные для работы с трехмерными векторами и трехмерными матрицами -- у меня теперь программа компилируется (собирается) и запускается.
RF>В связи с этим у меня к вам, уважаемые коллеги, вопрос: не могли бы вы посмотреть код этих файлов 3dvecmat.h и 3dvecmat.cpp и сказать, всё ли правильно в этих файлах?

RF>Файл 3dvecmat.h :


RF>
RF>    T3DVector& operator= (T3DVector v);
RF>    T3DVector& operator+=(T3DVector v);
RF>    T3DVector& operator-=(T3DVector v);
RF>    T3DVector& operator*=(T3DVector v);
RF>


Лучше
    T3DVector& operator= (const T3DVector &v);
    T3DVector& operator+=(const T3DVector &v);
    T3DVector& operator-=(const T3DVector &v);
    T3DVector& operator*=(const T3DVector &v);


Что бы не вызывать лишний раз конструктор копии при вызове операторов.



RF>Файл 3dvecmat.cpp :


RF>
RF>    LDouble& T3DVector::operator[](int i){return ((LDouble*)&x)[i-1];};
RF>


LDouble это что? typedef для double?
В объявлении класса LDouble x,y,z; и класс попадает под определение POD-класса. Но если в будущем в классе что-то изменится или код будет перенесён на другую архитектуру, то не факт, что x,y,z будут размещены в памяти друг за другом подряд, без пропусков. Ещё нет проверки на то, что i лежит в пределах 0..2.

Лучше заменить на что то вроде
    // Вместо x,y,z.
    std::array<LDouble, 3>    coor;
    // И добавить константы для обращения к координатам x,y,z по индексу.
    enum COOR : size_t
    {
        X = 0,
        Y,
        Z
    };
    // И сделать operator[]
    inline LDouble& T3DVector::operator[](COOR i){ return coor[i]; };
    // И там, где в классе надо обращаться к координатам, писать coor[X], coor[Y], coor[Z]


или на
    LDouble x,y,z;
    
    enum COOR
    {
        X = 0,
        Y,
        Z
    };
    // И сделать operator[]
    LDouble& T3DVector::operator[](int i)
    {
        switch(i)
        {
            case X: return x;
            case Y: return y;
            case Z: return z;
            default: throw std::invalid_argument(std::string("Invalid index ") + std::to_string(i) + " at T3DVector::operator[]");
        }
    };



RF>#define swap(X,Y)  tmp=(X),(X)=(Y),(Y)=tmp
RF>      swap(a[0][1],a[1][0]);
RF>      swap(a[0][2],a[2][0]);
RF>      swap(a[1][2],a[2][1]);
RF>     return *this;
RF>#undef swap

Зачем делать свой swap, если ещё с C++11 есть std::swap?

RF>            throw 777;

Что такое 777? Если какой-нибудь код ошибки, то лучше магические числа заменить константами.

    LDouble a[3][3];
    ...
    T3DVector& T3DMatrix::operator[](int i) { return *(T3DVector*)a[3*(i-1)];}


a объявлена как массив, а потом адрес одного из элементов массива приводится к указателю на класс??? Работает только потому, что это POD-класс, но это потенциальный источник больших проблем. И что будет, если i будет равно 0?
Переделать на std::array
    std::array<T3DVector, 3> a;
    ...
    inline T3DVector& T3DMatrix::operator[](size_t i) { return a[i];}