클래스의 함수 선언에서 'const'의 마지막 의미?


727

const이와 같은 선언 에서 의미는 무엇입니까 ? 은 const나를 혼란.

class foobar
{
  public:
     operator int () const;
     const char* foo() const;
};

답변:


951

const키워드를 메소드에 추가하면 this포인터는 기본적으로 const객체에 대한 포인터가 되므로 멤버 데이터를 변경할 수 없습니다. (를 사용하지 않으면 mutable나중에 자세히 설명).

const키워드는 두 개의 유사한 방법, 객체 인 경우라고 하나 구현할 수 있다는 것을 의미 기능 서명의 일부 const, 그리고 하나를.

#include <iostream>

class MyClass
{
private:
    int counter;
public:
    void Foo()
    { 
        std::cout << "Foo" << std::endl;    
    }

    void Foo() const
    {
        std::cout << "Foo const" << std::endl;
    }

};

int main()
{
    MyClass cc;
    const MyClass& ccc = cc;
    cc.Foo();
    ccc.Foo();
}

출력됩니다

Foo
Foo const

비 const 메소드에서는 const버전 에서 할 수없는 인스턴스 멤버를 변경할 수 있습니다 . 위의 예제에서 메소드 선언을 아래 코드로 변경하면 약간의 오류가 발생합니다.

    void Foo()
    {
        counter++; //this works
        std::cout << "Foo" << std::endl;    
    }

    void Foo() const
    {
        counter++; //this will not compile
        std::cout << "Foo const" << std::endl;
    }

멤버를 표시 할 수 mutable있고 const메서드를 변경할 수 있기 때문에 이는 사실이 아닙니다 . 내부 카운터 및 물건에 주로 사용됩니다. 그 해결책은 아래 코드입니다.

#include <iostream>

class MyClass
{
private:
    mutable int counter;
public:

    MyClass() : counter(0) {}

    void Foo()
    {
        counter++;
        std::cout << "Foo" << std::endl;    
    }

    void Foo() const
    {
        counter++;    // This works because counter is `mutable`
        std::cout << "Foo const" << std::endl;
    }

    int GetInvocations() const
    {
        return counter;
    }
};

int main(void)
{
    MyClass cc;
    const MyClass& ccc = cc;
    cc.Foo();
    ccc.Foo();
    std::cout << "Foo has been invoked " << ccc.GetInvocations() << " times" << std::endl;
}

어떤 출력

Foo
Foo const
Foo has been invoked 2 times


47

const규정 수단이 방법은 임의의 값으로 호출 될 수있다 foobar. const 객체에서 비 const 메소드를 호출 할 때 차이점이 있습니다. foobar유형에 다음과 같은 추가 메소드 선언이 있는지 고려하십시오 .

class foobar {
  ...
  const char* bar();
}

이 방법 bar()은 상수가 아니며 상수가 아닌 값에서만 액세스 할 수 있습니다.

void func1(const foobar& fb1, foobar& fb2) {
  const char* v1 = fb1.bar();  // won't compile
  const char* v2 = fb2.bar();  // works
}

그러나 아이디어 const는 클래스의 내부 상태를 변경하지 않는 메소드를 표시하는 것입니다. 이것은 강력한 개념이지만 실제로 C ++에서는 적용 할 수 없습니다. 그것은 보증보다 더 약속입니다. 그리고 종종 부서지고 쉽게 부서지는 것.

foobar& fbNonConst = const_cast<foobar&>(fb1);

3
대답은 const 객체가 아니라 다른 const 메소드에 대한 것이라고 생각했습니다.
Mykola Golubyev

" const하지만 뒤에 아이디어 는 클래스의 내부 상태를 변경하지 않는 메소드를 표시하는 것입니다." 그것이 내가 찾던 것입니다.
kovac

1
@JaredPar는 읽기 전용 작업을 나타내는 멤버 함수가 const? 로 표시되어야 함을 의미합니다 .
kovac

26

이러한 const는 'with const'메소드가 내부 데이터를 변경하면 컴파일러가 오류를 발생시킵니다.

class A
{
public:
    A():member_()
    {
    }

    int hashGetter() const
    {
        state_ = 1;
        return member_;
    }
    int goodGetter() const
    {
        return member_;
    }
    int getter() const
    {
        //member_ = 2; // error
        return member_;
    }
    int badGetter()
    {
        return member_;
    }
private:
    mutable int state_;
    int member_;
};

시험

int main()
{
    const A a1;
    a1.badGetter(); // doesn't work
    a1.goodGetter(); // works
    a1.hashGetter(); // works

    A a2;
    a2.badGetter(); // works
    a2.goodGetter(); // works
    a2.hashGetter(); // works
}

자세한 내용은 이것을 읽으십시오


1
변경const 불가능한 멤버 함수 에 대한 질문 은 불완전합니다.
IInspectable December

13

블레어의 대답은 표에있다.

그러나 mutable클래스의 데이터 멤버에 추가 될 수 있는 한정자가 있습니다. 이렇게 표시된 모든 구성원 은 계약 을 위반하지 않고 방법 으로 수정할 있습니다 .constconst

객체가 해당 메소드의 "논리적"제한에 영향을 미치지 않으면 서 특정 메소드가 몇 번이나 호출되는지 기억하도록하려는 경우이를 사용할 수 있습니다 (예 :).


10

C ++ 에서 Const 멤버 함수의 의미 상식 : 필수 중급 프로그래밍 은 다음과 같은 명확한 설명을 제공합니다.

X 클래스의 비 const 멤버 함수에서 this 포인터의 유형은 X * const입니다. 즉, 상수가 아닌 X에 대한 상수 포인터입니다 (const 포인터 및 Const에 대한 포인터 [7, 21] 참조). 이것이 참조하는 객체는 const가 아니기 때문에 수정할 수 있습니다. 클래스 X의 const 멤버 함수에서이 유형은 const X * const입니다. 즉, 상수 X에 대한 상수 포인터입니다.이 개체가 참조하는 개체가 const이므로 수정할 수 없습니다. const와 non-const 멤버 함수의 차이점입니다.

따라서 코드에서 :

class foobar
{
  public:
     operator int () const;
     const char* foo() const;
};

다음과 같이 생각할 수 있습니다.

class foobar
{
  public:
     operator int (const foobar * const this) const;
     const char* foo(const foobar * const this) const;
};

this아닙니다 const. 그것이 수정 될 수없는 이유는 그것이 prvalue이기 때문입니다.
Brian

7

const메소드 서명에 사용하면 (당신의 const char* foo() const;말 :) 컴파일러 this가이 메소드 ( foo여기있는)로 메모리를 변경할 수 없다고 말하고 있습니다 .


6

다음 사항을 추가하고 싶습니다.

또한 만들 수 있습니다 그것을 const &const &&

그래서,

struct s{
    void val1() const {
     // *this is const here. Hence this function cannot modify any member of *this
    }
    void val2() const & {
    // *this is const& here
    }
    void val3() const && {
    // The object calling this function should be const rvalue only.
    }
    void val4() && {
    // The object calling this function should be rvalue reference only.
    }

};

int main(){
  s a;
  a.val1(); //okay
  a.val2(); //okay
  // a.val3() not okay, a is not rvalue will be okay if called like
  std::move(a).val3(); // okay, move makes it a rvalue
}

답변을 자유롭게 개선하십시오. 나는 전문가가 아니다


1
*this멤버 함수가 rvalue-ref-qualified이고 rvalue에서 호출 되더라도 항상 lvalue입니다. .
HolyBlackCat

1
예, 그렇다면 현재 답변을 어떻게 개선해야합니까?
coder3101

블록에 의견을
써서

업데이트되었습니다. 괜찮아?
coder3101

2

CONST의 그것이라는 함수 선언 지정에 사용 키워드 CONST 멤버 함수 하고 것이다 변경할 수없는 물체의 데이터 멤버.


1

https://isocpp.org/wiki/faq/const-correctness#const-member-fns

" const멤버 기능" 이란 무엇입니까 ?

객체를 검사하지 않고 검사하는 멤버 함수입니다.

const멤버 함수는로 표시된다 const바로 멤버 함수의 파라미터리스트 후에 접미사. A의 멤버 함수 const접미사 "const 멤버 함수"또는라고 "검사." const접미사가 없는 멤버 함수를 "비 const 멤버 함수"또는 "돌연변이 자"라고합니다.

class Fred {
public:
  void inspect() const;   // This member promises NOT to change *this
  void mutate();          // This member function might change *this
};
void userCode(Fred& changeable, const Fred& unchangeable)
{
  changeable.inspect();   // Okay: doesn't change a changeable object
  changeable.mutate();    // Okay: changes a changeable object
  unchangeable.inspect(); // Okay: doesn't change an unchangeable object
  unchangeable.mutate();  // ERROR: attempt to change unchangeable object
}

호출 시도 unchangeable.mutate()는 컴파일시 오류가 발생했습니다. 에 대한 런타임 공간이나 속도 불이익이 없으며 런타임시 const이를 확인하기 위해 테스트 사례를 작성할 필요가 없습니다.

후행 constinspect()멤버 함수는 객체의 변경되지 않습니다 방법을 의미하는 것으로 사용되어야한다 추상 (클라이언트 표시) 상태를. 이는 메소드가 객체 구조체의 "원시 비트"를 변경하지 않는다고 말하는 것과는 약간 다릅니다. C ++ 컴파일러는 일반적으로 해결할 수없는 앨리어싱 문제를 해결할 수없는 경우 (즉, 객체의 상태를 수정할 수있는 불변의 별칭이 존재할 수있는 경우) "비트 단위"해석을 수행 할 수 없습니다. 이 앨리어싱 문제에 대한 또 다른 (중요한) 통찰력 : 포인터를 대상으로하는 객체를 가리켜도 객체가 변경되지 않는다는 보장은 없습니다. 단지 포인터를 통해 객체가 변경되지 않을 것이라고 약속합니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.