const antes do parâmetro vs const depois do nome da função c ++

86

Qual é a diferença entre algo assim

friend Circle copy(const Circle &);

e algo assim

friend Circle copy(Circle&) const;

Eu sei que const depois que a função é usada para dizer ao compilador que esta função não tentará alterar o objeto no qual é chamada, e a outra?

jazz
fonte
6
que você não vai mudar o parâmetro é o outro
Chad

Respostas:

194

A primeira forma significa que o (estado do) Circleobjeto vinculado à referência que é o parâmetro da copy()função não será alterado por copy()meio dessa referência. A referência é uma referência a const, portanto, não será possível invocar funções-membro de Circlepor meio dessa referência que não sejam qualificadas como const.

A segunda forma, por outro lado, é ilegal: apenas funções-membro podem ser constqualificadas (enquanto o que você está declarando lá é uma friendfunção global ).

Quando constqualifica uma função de membro, a qualificação se refere ao thisargumento implícito . Em outras palavras, essa função não terá permissão para alterar o estado do objeto em que é chamada (o objeto apontado pelo thisponteiro implícito ) - com exceção dos mutableobjetos, mas isso é outra história.

Para dizer com código:

struct X
{
    void foo() const // <== The implicit "this" pointer is const-qualified!
    {
        _x = 42; // ERROR! The "this" pointer is implicitly const
        _y = 42; // OK (_y is mutable)
    }

    void bar(X& obj) const // <== The implicit "this" pointer is const-qualified!
    {
        obj._x = 42; // OK! obj is a reference to non-const
        _x = 42; // ERROR! The "this" pointer is implicitly const
    }

    void bar(X const& obj) // <== The implicit "this" pointer is NOT const-qualified!
    {
        obj._x = 42; // ERROR! obj is a reference to const
        obj._y = 42; // OK! obj is a reference to const, but _y is mutable
        _x = 42; // OK! The "this" pointer is implicitly non-const
    }

    int _x;
    mutable int _y;
};
Andy Prowl
fonte
11
Helluva resposta! Obrigado!
SexyBeast de
1
Então, para o segundo caso, se eu tenho um constobjeto objde classe X, e eu chamo bar()assim obj.bar(obj), o que deve acontecer e por quê? Não deve obj._x = 42falhar, uma vez que objé declarado constno chamador?
SexyBeast
1
E o caso em que você faz a última função da barra ( void bar(X const& obj) {...}) se parecer com isso? void bar(const X& obj) {...}, mover a constpalavra-chave para este local muda alguma coisa? Em caso afirmativo, você pode adicionar este exemplo também?
Gabriel Staples
1
@GabrielStaples Eles são iguais; constaplica-se ao que está à sua esquerda ou ao que está à sua direita, caso não haja nada à esquerda. No seu caso, você verá que para ambas as versões consté aplicado a X.
Andreas Flöjt
69

Os métodos da classe C ++ têm um thisparâmetro implícito que vem antes de todos os explícitos. Portanto, uma função declarada dentro de uma classe como esta:

class C {
  void f(int x);

Você pode imaginar que realmente se parece com isto:

  void f(C* this, int x);

Agora, se você declarar desta forma:

  void f(int x) const;

É como se você escrevesse isto:

  void f(const C* this, int x);

Ou seja, o trailing consttorna o thisparâmetro const, o que significa que você pode invocar o método em objetos const do tipo de classe e que o método não pode modificar o objeto no qual foi invocado (pelo menos, não por meio dos canais normais).

John Zwinck
fonte
2
Perfeitamente correto, entretanto, não responde à pergunta, que não está realmente se referindo a um método de classe, mas sim a uma função amiga.
maio de
5
Sim, optei por ignorar a friendparte porque acho que é realmente irrelevante para a verdadeira questão do OP (ou o que a verdadeira questão se tornará quando todos os problemas vierem à tona). Que assim seja.
John Zwinck,
Acho que é um pouco enganador dizer "você pode invocar o método em objetos const do tipo de classe" porque você pode invocar o método const em objetos const ou objetos não const, enquanto funções não const só podem ser chamadas por objetos não const. caso contrário, esta é a minha resposta favorita
csguy
8
Circle copy(Circle&) const;

faz a constprópria função . Isso só pode ser usado para funções de membro de uma classe / estrutura.

Fazer uma função de membro constsignifica que

  • não pode chamar nenhuma função membro não const
  • não pode alterar nenhuma variável de membro.
  • ele pode ser chamado por um constobjeto (os constobjetos só podem chamar constfunções). Objetos não constantes também podem chamar uma constfunção.
  • Ele deve ser função membro da classe ' círculo '.

Agora considere o próximo:

Circle copy(const Circle &);

enquanto este significa que o parâmetro passado não pode ser alterado dentro da função. Pode ou não ser uma função de membro da classe.

NOTA: É possível sobrecarregar uma função de forma a ter uma constversão e não const da mesma função.

Waqar
fonte
7

VAMOS ESCLARECER TODAS AS CONFUSÕES RELACIONADAS A const


constveio de constante significa que algo não é mutável, mas legível.

  1. se qualificarmos nossa variável com constpalavra - chave, não podemos alterá-la mais tarde.
    por exemplo, a variável const deve ser inicializada ao ser declarada.
    constint var =25;
    var =50; // gives error

  2. se qualificarmos nossa variável de ponteiro com after , não poderemos alterar o ponteiro em si, mas o conteúdo do ponteiro pode ser alterado . por exemplo, // masconst *

    int *const ptr = new int;
    ptr = new int; //gives error

    *ptr=5445; //allowed

  3. se nos qualificarmos nossa variável ponteiro com antes , então nós pode mudar ponteiro em si, mas o conteúdo do ponteiro é não alterável . por exemplo, // masconst *

    intconst* ptr = new int(85);
    //or
    constint * ptr = new int(85);
    ptr = new int; // allowed

    *ptr=5445; // gives error

  4. ponteiro e conteúdo constantes,
    por exemplo
    intconst*constptr = new int(85);
    //or
    constint *constptr = new int(85);
    ptr = new int; // not allowed
    *ptr=5445; // not allowed


  1. Circle copy(const Circle &);
    aqui const Circle significa que o valor de Circle é apenas legível, se tentarmos alterar o valor de Circle dentro da função, ocorrerá um erro.
  2. friend Circle copy(Circle&) const;
    Este tipo de função não é para variáveis ​​não membros. Ela é usada para classe ou estrutura. Aqui, toda a função é qualificada com a palavra-chave const significa que não podemos alterar a variável membro do objeto . por exemplo
    class A{ public :
              int  var;
              void fun1()
                    { var = 50; // allowed
                    } 
              void fun2()const
                       { var=50; //not allowed
                       }
           }; 
Ramesh Choudhary
fonte
4

Um se refere ao parâmetro e o outro à função.

Circle copy(const Circle &);

Isso significa que o parâmetro passado não pode ser alterado dentro da função

Circle copy(Circle&) const;

A constfunção qualificada é usada para funções de membro e significa que você não pode alterar os membros de dados do próprio objeto. O exemplo que você postou era sem sentido.

Leia da direita para a esquerda

Se reescrevermos a primeira função como Circle copy(Circle const&);, o que significa a mesma coisa, fica claro que ler da direita para a esquerda se torna útil. copyé uma função que faz constreferência a um Circleobjeto e retorna um Circleobjeto por referência.

Alex Chamberlain
fonte
0

friend Circle copy(const Circle &);// refere-se ao parâmetro constante da função. não pode 'alterar o valor armazenado por parâmetro.

Precisa remover o amigo em sua cópia do círculo de exemplo (Círculo &) const; // não pode alterar este valor poniter nomeado como função de membro constante

Shivakumar
fonte
-1
friend Circle copy(const Circle &);

O valor do parâmetro não será alterado durante as chamadas de função.

friend Circle copy(const Circle &)const ; 

A função é um acessador que não altera nenhum valor dos membros da classe. Geralmente, existem tipos de funções: acessores e modificadores. Acessador: examina, mas não altera o estado de seu objeto.

Sam
fonte