Страницы

Поиск по вопросам

воскресенье, 2 февраля 2020 г.

Перегрузка оператор С++

#cpp #перегрузка_операторов #операторы


Такой вопрос. Я перегружаю операторы для работы с вектором, который состоит из трек
точек. Есть несколько задач:


Найти скалярное произведения векторов; (возвращает double)
Найти векторное произведения векторов; (возвращает вектор)


И получается такая проблема, что компилятор не знает какой из двух методов вызвать
(хотя они отличаются возвращающимися параметрами). И как все это решить?

using namespace std;
class Vec3D
{
private:
    double x, y, z;
public:
    Vec3D(double xx = 0, double yy = 0, double zz =0);
    Vec3D operator+ (const Vec3D & V);
//  double operator* (const Vec3D & V); // проблема тут
    friend ostream& operator<< (ostream& cout, Vec3D & V);
    friend Vec3D operator* (const double c, const Vec3D & V);   
    friend Vec3D operator* (const Vec3D & V1,const Vec3D & V2); // и тут
};


P.S. То что нужно реализовать семеричные\бинарные операции через friend функции я знаю
    


Ответы

Ответ 1



Компилятор в общем случае не может определить, какую вызывать перегруженную функцию только по возвращаемому значению. Например, рассмотрите следующий фрагмент кода void f() {} int f() { return 0; } f(); Как определить, какая функция из двух вызывается? Поэтому функции не перегружаются по возвращаемому значению. Перегрузите этот оператор следующим образом, как показано в демонстрационной программе ниже. #include class Vec3D { private: double x, y, z; public: Vec3D( double x = 0, double y = 0, double z =0) : x( x ), y( y ), z( z ) { } friend std::ostream & operator <<( std::ostream &os, const Vec3D &v ); friend Vec3D operator *( const Vec3D &V, double d ); friend Vec3D operator *( double d, const Vec3D &v ); friend Vec3D operator *( const Vec3D &V1, const Vec3D &V2 ); // и тут }; std::ostream & operator <<( std::ostream &os, const Vec3D &v ) { return os << "( " << v.x << ", " << v.y << ", " << v.z << " )"; } Vec3D operator *( const Vec3D &v, double d ) { return Vec3D( d * v.x, d * v.y, d * v.z ); } Vec3D operator *( double d, const Vec3D &v ) { return v * d; } Vec3D operator *( const Vec3D &v1, const Vec3D &v2 ) { return Vec3D( v1.x * v2.x, v1.y * v2.y, v1.z * v2.z ); } int main() { Vec3D v1( 1, 2, 3 ); Vec3D v2( 1, 2, 3 ); std::cout << ( 2 * v1 ) * ( v2 * 3 ) << std::endl; return 0; } Ее вывод на консоль ( 6, 24, 54 ) Нельзя перегрузить оператор по возвращаемому типу. Но вы могли бы взять еще один оператор, как, например, operator ^, чтобы использовать его для одного из видов произведения векторов. В итоге у вас может получиться два оператора operator * и operator ^ Объявление перегруженного оператора operator ^ может выглядеть аналогично объявлению оператора operator * за исключением типа возвращаемого значения.

Ответ 2



Понятие сигнатуры функции не включает возвращаемый тип, поэтому использовать перегрузку для одинаковых типов параметров, но разных возвращаемых типов в C++ нельзя. Увы, решайте проблему иначе... P.S. Недаром они даже в математике обозначаются по-разному :)

Ответ 3



Тут можно постараться и сделать, например, такое (но это не означает, что так делать надо): http://ideone.com/8wAlaK #include struct v3d { double x, y, z; }; struct v3d_mr // multiplication result { double scalar; v3d vector; operator double () { return this->scalar; } operator v3d () { return this->vector; } }; v3d_mr operator * (const v3d &a, const v3d &b) { return { a.x*b.x + a.y*b.y + a.z*b.z, { a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - b.x*a.y } }; } int main() { v3d a = {1, 2, 3}, b = {4, 5, 6}; double s = a * b; v3d v = a * b; printf("%lf\n", s); printf("%lf %lf %lf\n", v.x, v.y, v.z); return 0; }

Комментариев нет:

Отправить комментарий