O que 'const' faz na sobrecarga de operador ()?
-
23-09-2019 - |
Pergunta
Eu tenho uma base de código, na qual para a classe Matrix, essas duas definições existem para ()
operador:
template <class T> T& Matrix<T>::operator() (unsigned row, unsigned col)
{
......
}
template <class T> T Matrix<T>::operator() (unsigned row, unsigned col) const
{
......
}
Uma coisa que entendo é que o segundo não retorna a referência e sim o que const
significa na segunda declaração?Além disso, qual função é chamada quando eu digo mat(i,j)
?
Solução
Qual função é chamada depende se a instância é constante ou não. A primeira versão permite modificar a instância:
Matrix<int> matrix;
matrix(0, 0) = 10;
A sobrecarga const permite acesso somente leitura se você tiver uma instância const (referência) da matriz:
void foo(const Matrix<int>& m)
{
int i = m(0, 0);
//...
//m(1, 2) = 4; //won't compile
}
O segundo não retorna uma referência, pois a intenção é proibir a modificação do objeto (você obtém uma cópia do valor e, portanto, não pode modificar a instância da matriz).
Aqui, deve ser um tipo numérico simples, que é barato (er) para retornar por valor. Se T também pudesse ser um tipo mais complexo definido pelo usuário, também seria comum para que as sobrecargas const retornem uma referência const:
template <class T>
class MyContainer
{
//..,
T& operator[](size_t);
const T& operator[](size_t) const;
}
Outras dicas
A versão const será chamada em matrizes const. Nas matrizes não consagras, a versão não-consiga será chamada.
Matrix<int> M;
int i = M(1,2); // Calls non-const version since M is not const
M(1,2) = 7; // Calls non-const version since M is not const
const Matrix<int> MConst;
int j = MConst(1,2); // Calls const version since MConst is const
MConst(1,2) = 4; // Calls the const version since MConst is const.
// Probably shouldn't compile .. but might since return value is
// T not const T.
int get_first( const Matrix<int> & m )
{
return m(0,0); // Calls the const version as m is const reference
}
int set_first( Matrix<int> & m )
{
m(0,0) = 1; // Calls the non-const version as m is not const
}
Qual função é chamada depende se o objeto é const
.Para const
objetos const
sobrecarga é chamada:
const Matrix<...> mat;
const Matrix<...>& matRef = mat;
mat( i, j);//const overload is called;
matRef(i, j); //const overloadis called
Matrix<...> mat2;
mat2(i,j);//non-const is called
Matrix<...>& mat2Ref = mat2;
mat2Ref(i,j);//non-const is called
const Matrix<...>& mat2ConstRef = mat2;
mat2ConstRef(i,j);// const is called
O mesmo se aplica aos ponteiros.Se a chamada for feita por meio de um ponteiro para const, uma sobrecarga const será chamada.Caso contrário, uma sobrecarga não const será chamada.