Перегруженный оператор никогда не вызывается в C ++ - PullRequest
0 голосов
/ 14 февраля 2010

Я пишу математическую библиотеку в качестве практического упражнения. Я столкнулся с некоторыми проблемами при перегрузке оператора =. Когда я его отладил, я заметил, что вызов vertex1 = vertex2 вызывает вместо этого конструктор копирования.

В заголовочном файле у меня есть:

//constructors
vector3();
vector3( vector3 &v );
vector3(float ix, float iy, float iz);

//operator overloading
vector3 operator =(vector3 p);
....

В исходном файле я реализовал:

vector3 vector3::operator =(vector3 p)
{
    vector3 v3;
    v3.x = p.x;
    v3.y = p.y;
    v3.z = p.z;
    return v3;
}

Позже у меня есть метод перекрестного продукта, и я хочу использовать его так:

vector3 v3;
v3 = v1.crossProduct(v2);

Сообщение об ошибке: ошибка: нет соответствующей функции для вызова `vector3 :: vector3 (vector3) ' но я не хочу вызывать конструктор копирования.

Ответы [ 6 ]

4 голосов
/ 14 февраля 2010

В вашем коде есть ошибки. Ваш конструктор копирования должен занять const&. Ссылка позволит избежать создания копии (что вы не сможете сделать, будучи конструктором копирования), и она должна быть const, поскольку вы не изменяете ее:

vector3(const vector3&);

Временные переменные могут быть связаны с const&, но не может быть привязанным к изменяемой ссылке. То есть со своим кодом вы могли бы сделать:

vector3 a;
vector3 b(a);

но не:

vector3 a(some_calculation()); // some_calculation returns a vector3

Кроме того, ваш operator= неверен. Как и конструктор копирования, он обычно должен принимать const&, , но должен возвращать ссылку на this. Вот как работает цепочка:

int a, b, c;
a = b = c = 0;
// a.operator=(b.operator=(c.operator=(0)));

Возвращение временного неортодоксально и ничего не дает. В вашем случае вы можете назначать снова и снова и никогда не изменять значение. Weird

vector 3 a, b;
a = b; // doesn't change a...?!

operator= необходимо изменить this.

2 голосов
/ 14 февраля 2010

Я не хочу вызывать конструктор копирования.

То, что вы хотите, не имеет значения.Вам нужен конструктор копирования здесь.operator = не вызывается в этой ситуации, конструктор копирования есть.Кроме того, подпись неверна, она должна быть

vector3& operator =(vector3 const& other);

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

(подпись вашего конструктора копирования также нетрадиционна, см. ответ Джеймса.)

2 голосов
/ 14 февраля 2010

vector3 (vector3 & v);

Это действительно должно быть vector3( const vector3 &v );

Поскольку вы возвращаете временное значение, вы должны вызвать конструктор копирования, который принимает константную ссылку.

1 голос
/ 14 февраля 2010

Хорошей практикой в ​​C ++ является выполнение одной из двух вещей в зависимости от того, хотите ли вы, чтобы ваш объект был копируемым (т.е. назначаемым для другой переменной) или нет. Если вам нужно, вы должны предоставить как оператор присвоения, так и конструктор копирования. Например:

class Point
{
public:
    Point ()                          { }
    Point (int x, int y)              : mX(x), mY(y) { }
    Point (const Point& p)            : mX(p.mX), mY(p,mY) { }

    Point& operator = (const Point& p)    { mX = p.mX; mY = p.mY; return *this; }

    int X () const                    { return mX; }
    int Y () const                    { return mY; }

private:
    int mX;
    int mY;
};

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

Всякий раз, когда вы используете этот вид кода:

Point P = anotherP;

будет вызван конструктор копирования. Если вы используете этот тип кода:

Point P;
P = anotherP;

будет вызван оператор присваивания.

Надеюсь, это поможет.

1 голос
/ 14 февраля 2010

Сделайте vector3 vector3::operator =(vector3 p) вместо этого используйте ссылки, чтобы вам не нужно было создавать копию.

vector3& vector3::operator =(vector3& p);

Вы все равно не хотели создавать скопированный объект.

0 голосов
/ 14 февраля 2010

Когда вы "передаете по значению", как в своем определении оператора =, создается копия типа для использования в качестве локального значения для метода. Ваш оператор не вызывается, потому что система не может найти конструктор, который принимает vector3 - вы определили конструктор копирования, который принимает vector3 &.

Поэтому, как уже говорили другие, вы хотите определить своего оператора = как принимающего

const vector3& p

Вам также следует обновить объявленный вами конструктор копирования, чтобы он также использовал const vector3.

...