Const exactidão em C ++ operador sobrecarga retornos
-
08-07-2019 - |
Pergunta
Estou um pouco confuso sobre o porquê eu tenho dito para retornar foo const de um operador binário em c ++ em vez de apenas foo.
Eu estive lendo "Pensando em C ++" de Bruce Eckel e no capítulo sobre a sobrecarga de operadores, ele diz que "fazendo o valor de retorno [de um operador binário sobrecarga] const, você estado que só um const função de membro pode ser chamado para esse valor de retorno. Este é const-correta, porque o impede de armazenar informação potencialmente valiosa em um objeto que será mais provável ser perdido".
No entanto, se eu tiver um operador mais que os retornos const, e um operador de incremento de prefixo, este código é inválido:
class Integer{
int i;
public:
Integer(int ii): i(ii){ }
Integer(Integer&);
const Integer operator+();
Integer operator++();
};
int main(){
Integer a(0);
Integer b(1);
Integer c( ++(a + b));
}
Para permitir que este tipo de atribuição, não faria sentido ter o operador + retornar um valor não-const? Isso poderia ser feito através da adição de const_casts, mas isso fica bastante volumoso, não é?
Obrigado!
Solução
Quando você diz ++ x, você está dizendo "adicionar 1 a x, armazenar parte de trás resultado em x, e diga-me o que era". Este é o operador de pré-incremento. Mas, em ++ (a + b), como você é suposto para "armazenar parte de trás resultado em a + b"?
Certamente você pode armazenar a parte de trás resultado na temporário, que está ocupando o resultado de a + b, que desapareceria em breve. Mas se você realmente não me importo onde o resultado foi armazenado, por que você incrementa-lo em vez de apenas adicionar um?
Outras dicas
FYI, ++(a + b)
é ilegal mesmo com vagens (tipos de dados antigos simples, como int
). Portanto, faz sentido para não permitir-lo para seus próprios tipos de classe também. Tente isto:
int a = 1;
int b = 2;
int c = ++(a+b);
CCG retornos error: lvalue required as increment operand
.
No seu caso, seria preferível fazer o seu construtor de cópia ter um argumento const Integer
, e criar seu Integer c
como este em vez disso:
Integer c(a + b + Integer(1));
Copiar construtores tomam geralmente um const referência, resolver esse problema para você.
(Ter ctor cópia não-const implica alguma transferência de recursos, que pode ser, por vezes, útil, mas para 99% de todas as situações, não é necessário)
Eu acredito que o exemplo do OP seria adequado para a questão se o operador de adição é substituído com qualquer outro operador binário que retorna uma referência, por exemplo, um operador de atribuição:
Integer c( ++(a = b));
Eu vim aqui me perguntando se eu deveria fazer o meu operador de atribuição retorna um const ou uma referência não-const. alguns tutoriais usar versões não-const, ao contrário do "pensando em C ++" 's conselhos. E algumas outras referências dão raciocínio por trás disso:
Observe que a referência retornado não é declarado const. Isso pode ser um pouco confuso, porque ele permite que você escreva coisas loucas como esta:
MyClass a, b, c;
...
(a = b) = C; // O que ??
À primeira vista, você pode querer evitar situações como esta, por ter operator = retornar uma referência const. No entanto, declarações como isso vai funcionar com tipos primitivos. E, pior ainda, algumas ferramentas realmente contar com esse comportamento. Portanto, é importante para retornar uma referência não-const de seus = operador. A regra de ouro é: "Se é bom o suficiente para ints, é bom o suficiente para tipos de dados definidos pelo usuário."