Operador sobrecarregado nunca é chamado em C++
-
20-09-2019 - |
Pergunta
Estou escrevendo uma biblioteca de matemática como um exercício prático.Encontrei alguns problemas ao sobrecarregar o operador =.Quando depurei, percebi que a chamada para vertex1 = vertex2 chama o construtor de cópia.
No arquivo de cabeçalho eu tenho:
//constructors
vector3();
vector3( vector3 &v );
vector3(float ix, float iy, float iz);
//operator overloading
vector3 operator =(vector3 p);
....
No arquivo fonte eu implementei:
vector3 vector3::operator =(vector3 p)
{
vector3 v3;
v3.x = p.x;
v3.y = p.y;
v3.z = p.z;
return v3;
}
Mais tarde, tenho um método de produto cruzado e quero usá-lo da seguinte forma:
vector3 v3;
v3 = v1.crossProduct(v2);
A mensagem de erro é:erro:Nenhuma função de correspondência para Call to `Vector3 :: Vector3 (Vector3) ', mas não quero chamar o construtor de cópias.
Solução
Existem erros no seu código.Seu construtor de cópia deve levar um const&
.A referência evitará fazer uma cópia (o que você não conseguiria fazer sendo o construtor da cópia), e deve ser const
já que você não está modificando:
vector3(const vector3&);
Variáveis temporárias podem ser vinculadas a const&
, mas não pode estar vinculado a uma referência mutável.Ou seja, com seu código você poderia fazer:
vector3 a;
vector3 b(a);
mas não:
vector3 a(some_calculation()); // some_calculation returns a vector3
Além disso, seu operator=
está incorreto.Assim como o construtor de cópia, geralmente deve levar um tempo const&
, mas deve retornar uma referência para this
.É assim que funciona o encadeamento:
int a, b, c;
a = b = c = 0;
// a.operator=(b.operator=(c.operator=(0)));
Devolver um temporário é pouco ortodoxo e não leva a nada.No seu caso, você poderia atribuir repetidamente e nunca alterar o valor. Esquisito:
vector 3 a, b;
a = b; // doesn't change a...?!
operator=
precisa mudar this
.
Outras dicas
Vector3 (Vector3 e V);
Isso realmente deveria ser vector3( const vector3 &v );
Como você retorna um valor temporário, você deve ligar para um construtor de cópias que requer uma referência const.
Não quero chamar o construtor de cópias.
O que você quer é irrelevante. Você precisar um construtor de cópia aqui. operator =
Não é chamado nessa situação, o construtor de cópias é. Além disso, a assinatura está errada, deve ser
vector3& operator =(vector3 const& other);
O argumento também pode ser passado por valor (mas este é um truque avançado ...), mas o valor de retorno verdade devo Seja uma referência não consultiva.
(A assinatura do seu construtor de cópias também não é convencional, consulte a resposta de James.)
Faço vector3 vector3::operator =(vector3 p)
Use referências para que você não precise criar uma cópia.
vector3& vector3::operator =(vector3& p);
Você não queria criar um objeto copiado em primeiro lugar.
É uma boa prática em C ++ fazer uma das duas coisas, dependendo se você deseja que seu objeto seja copiado (ou seja, atribuível a outra variável) ou não. Se você precisar fornecer o operador e o construtor de cópias. Por exemplo:
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;
};
Se você não quiser copiar, pode colocar o protótipo do construtor de cópias e do operador atribuído em uma seção particular e não fornecer uma implementação. Qualquer tentativa de copiá -lo fornecerá um erro do compilador.
Sempre que você usa esse tipo de código:
Point P = anotherP;
O construtor de cópias será chamado. Se você usar esse tipo de código:
Point P;
P = anotherP;
O operador atribui será chamado.
Espero que ajude.
Quando você "passa por valor", como você está em sua definição de operador =, uma cópia do tipo é feita para usar um valor como local para o método. Seu operador não está sendo chamado porque o sistema não consegue encontrar um contrato que pega o Vector3 - você definiu um construtor de cópia que leva o Vector3 &.
Portanto, como outros declararam, o que você deseja fazer é definir seu operador = como tomar
const vector3& p
Você também deve atualizar seu construtor de cópia declarada para tomar o const Vector3 também.