자바의 최종 대 C ++의 const


답변:


195

C ++ 표시에서 멤버 함수 constconst인스턴스에서 호출 될 수 있음을 의미합니다 . Java에는 이와 동등한 것이 없습니다. 예 :

class Foo {
public:
   void bar();
   void foo() const;
};

void test(const Foo& i) {
   i.foo(); //fine
   i.bar(); //error
}

값은 나중에 Java에서만 한 번만 지정할 수 있습니다.

public class Foo {
   void bar() {
     final int a;
     a = 10;
   }
}

Java에서는 합법적이지만 C ++에서는 합법적이지 않습니다.

public class Foo {
   void bar() {
     final int a;
     a = 10;
     a = 11; // Not legal, even in Java: a has already been assigned a value.
   }
}

Java와 C ++에서 멤버 변수는 각각 final/ 일 수 있습니다 const. 클래스 인스턴스 생성이 완료 될 때까지 값을 제공해야합니다.

Java에서는 생성자가 완료되기 전에 설정해야하며, 다음 두 가지 방법 중 하나로 수행 할 수 있습니다.

public class Foo {
   private final int a;
   private final int b = 11;
   public Foo() {
      a = 10;
   }
}

C ++에서는 const멤버쉽에 값 을 제공하기 위해 초기화 목록을 사용해야 합니다.

class Foo {
   const int a;
public:
   Foo() : a(10) {
      // Assignment here with = would not be legal
   }
};

Java에서는 final을 사용하여 무시할 수없는 것으로 표시 할 수 있습니다. C ++ (pre-C ++ 11)은이 작업을 수행하지 않습니다. 예 :

public class Bar {
   public final void foo() {
   }
}

public class Error extends Bar {
   // Error in java, can't override
   public void foo() {
   }
}

그러나 C ++에서 :

class Bar {
public:
   virtual void foo() const {
   }
};

class Error: public Bar {
public:
   // Fine in C++
   virtual void foo() const {
   }
};

멤버 함수를 표시하는 의미가 다르기 때문에 이것은 const좋습니다. 멤버 함수 중 하나만 사용하여 오버로드 할 수도 const있습니다 (C ++ 11에서는 멤버 함수를 최종으로 표시 할 수 있습니다 (C ++ 11 업데이트 섹션 참조).)


C ++ 11 업데이트 :

C ++ 11을 사용하면 finalJava와 같은 Java의 동일한 기능에 대해 동일한 의미 로 클래스와 멤버 함수를 모두로 표시 할 수 있습니다 .

public class Bar {
   public final void foo() {
   }
}

public class Error extends Bar {
   // Error in java, can't override
   public void foo() {
   }
}

이제 C ++ 11에서 다음과 같이 정확하게 작성할 수 있습니다.

class Bar {
public:
  virtual void foo() final;
};

class Error : public Bar {
public:
  virtual void foo() final;
};

이 예제는 G ++ 4.7의 시험판으로 컴파일해야했습니다. const이것은이 경우를 대체 하는 것이 아니라 가장 근접한 C ++ 키워드로는 보이지 않는 Java와 유사한 동작을 제공하여 기능을 보강한다는 점에 유의하십시오. 따라서 멤버 함수를 모두 원한다면 다음 final과 같이 const하십시오.

class Bar {
public:
  virtual void foo() const final;
};

( constfinal여기 의 순서 가 필요합니다).

이전에는 const멤버 함수 와 직접적으로 동등한 기능이 없었지만 virtual컴파일 타임에 오류를 발생시키지 않으면 서 함수를 비 만드는 것은 잠재적 인 옵션 일 수 있습니다.

마찬가지로 자바 :

public final class Bar {
}

public class Error extends Bar {
}

C ++ 11이됩니다.

class Bar final {
};

class Error : public Bar {
};

(이전에는 private생성자가 C ++에서 가장 근접했을 것입니다)

흥미롭게도 C ++ 11 이전 코드와의 호환성을 유지하기 위해 일반적인 방식으로 키워드 final 가 아닙니다 . (사소하고 합법적 인 C ++ 98 예제 struct final;를 통해 키워드로 만드는 것이 코드를 깨뜨리는 이유를 확인하십시오)


3
이러한 방법을 가상으로 만들어야합니다. 그렇지 않으면, 당신은 정말로 같은 일을하지 않습니다
BlueRaja-Danny Pflughoeft

1
마지막 예제에서, 당신이 가진 것은 합법적이지만, 그렇지 final int a; a = 10; a = 11;않다는 것을 언급 할 가치가 final있습니다. .
corsiKa

2
C ++ 0x는 final이 정확한 목적을 위해 멤버 함수 데코레이터를 추가합니다 . VC ++ 2005 년, 2008 년, 및 2010 년 이미 문맥 키워드 사용이 구현 sealed보다는를 final.
ildjarn

@ildjarn-그것은 흥미롭고 내가 알지 못하는 또 다른 비교적 작은 C ++ 0x 변경입니다! 아마도 C ++ 0x로 변경되고 있음을 나타내는 텍스트 어딘가에 작은 주석을 추가 할 것입니다.
Flexo

1
분명히 사람들은 여전히 결과 로 finalructor 와 함께 코드베이스에서 여전히 s / const / final / g를 수행합니다!
Flexo

30

Java에서는 최종 키워드를 다음 네 가지 용도로 사용할 수 있습니다.

  • 그것을 봉인하는 클래스 또는 메소드 (서브 클래스 / 재정의는 허용되지 않음)
  • 멤버 변수에 선언하면 정확히 한 번만 설정할 수 있습니다 (이것이 당신이 말하는 것입니다)
  • 메소드에 선언 된 변수에서 정확히 한 번만 설정할 수 있는지 확인
  • 메소드 매개 변수에서 메소드 내에서 수정할 수 없음을 선언

한 가지 중요한 것은 : Java 최종 멤버 변수 정확히 한 번 설정 해야합니다 ! 예를 들어 생성자, 필드 선언 또는 초기화 프로그램에서. 그러나 메소드에서 최종 멤버 변수를 설정할 수는 없습니다.

멤버 변수를 final로 만드는 또 다른 결과는 메모리 모델과 관련이 있으며, 이는 스레드 환경에서 작업하는 경우 중요합니다.


'메모리 모델'이란 무엇을 의미합니까? 나는 그것을 얻지 못한다.
Tony

1
@Tony : Java 언어 사양, 17.4 장. 메모리 모델 -docs.oracle.com/javase/specs/jls/se8/html/index.html-Google 의 첫 히트
Ralph

27

const객체는 호출 할 수있는 const방법을 일반적으로 불변의 것으로 간주됩니다.

const Person* person = myself;
person = otherPerson; //Valid... unless we declared it const Person* const!
person->setAge(20); //Invalid, assuming setAge isn't a const method (it shouldn't be)

final객체는 새로운 객체로 설정할 수 없습니다, 그러나 그것은 불변하지 않습니다 수 있습니다 - 모든 전화에서 누군가를 중지 아무것도 없다 set방법.

final Person person = myself;
person = otherPerson; //Invalid
person.setAge(20); //Valid!

Java는 객체를 불변으로 선언하는 고유의 방법이 없습니다. 클래스를 변경할 수없는 것으로 디자인해야합니다.

변수가 기본 유형 인 경우 final/ const동일하게 작동합니다.

const int a = 10; //C++
final int a = 10; //Java
a = 11; //Invalid in both languages

3
이것은 다른 많은 사람들과 마찬가지로 훌륭한 답변입니다. 불행히도, 나는 하나의 대답 만 받아 들일 수 있습니다. :)
WinWin

1
완벽한 답변!
ADJ

13

Java final은 기본 값 유형의 C ++ const와 같습니다.

Java 참조 유형을 사용하면 final 키워드는 const 포인터와 같습니다. 즉

//java
final int finalInt = 5;
final MyObject finalReference = new MyObject();

//C++
const int constInt = 5;
MyObject * const constPointer = new MyObject();

"최종 키워드는 const 포인터와 동일합니다"
ADJ

8

여기에 이미 훌륭한 답변이 있지만 추가 할 가치가있는 한 가지 점이 있습니다 const.C ++에서는 일반적으로 프로그램의 다른 부분이 객체의 상태를 변경하지 못하게합니다. 지적했듯이, final자바에서는 이것을 할 수 없습니다 (원시적 제외)- 참조 가 다른 객체로 변경되는 것을 막습니다 . 그러나 Collection를 사용하는 경우 정적 메소드를 사용하여 객체 변경을 방지 할 수 있습니다

 Collection.unmodifiableCollection( myCollection ) 

이것은 Collection요소에 대한 읽기 액세스를 제공 하는 참조를 반환 하지만 수정이 시도되면 예외를 throw하여 constC ++에서 와 비슷하게 만듭니다.


8

Java final는 기본 유형 및 참조에서만 작동하며 const 키워드가 어떤 객체에서도 작동하는 객체 인스턴스 자체에서는 작동하지 않습니다.

첫 번째 const list<int> melist;와 비교 final List<Integer> melist;하면 목록을 수정할 수 없지만 후자는 새 목록을에 할당 할 수 없습니다 melist.


3

특정한 미묘한 멀티 스레딩 속성 을 갖는 것 외에도 선언 된 변수는 선언시 final초기화 할 필요가 없습니다!

즉, 이것은 자바에서 유효합니다 :

// declare the variable
final int foo;

{
    // do something...

    // and then initialize the variable
    foo = ...;
}

C ++로 작성된 경우에는 유효하지 않습니다 const.


2

Wikipedia 에 따르면 :

  • C ++에서 const 필드는 재 할당되지 않을뿐만 아니라 const 메소드 만 호출 할 수 있고 다른 메소드의 const 인수로만 전달 될 수 있다는 추가 제한 사항이 있습니다.
  • 비 정적 내부 클래스는 최종 클래스의 유무에 관계없이 포함 클래스의 모든 필드에 자유롭게 액세스 할 수 있습니다.

1
'재 할당 된'이라는 단어는 해당 페이지의 현재 버전에 나타나지 않으며, '액세스'의 의미에 따라 두 번째 요점과 유사한 내용도 잘못되었거나 관련이 없습니다. '정적 내부'는 이중 대화입니다. Wikipedia는 C ++ 또는 Java에 대한 규범적인 참조가 아닙니다.
Lorne의 후작

2

const포인터에 대해 이야기 할 때 C ++ 의 의미 가 복잡해 지기 때문에 상수 객체에 대한 포인터와 상수 포인터에 대한 포인터가 "거의"라고 추측 합니다. Java에는 "명시 적"포인터 final가 없으므로 이러한 문제가 없습니다.


1

switch / case 문의 예를 통해 이해 한 내용을 설명하겠습니다.

각 경우 명령문의 값은 스위치 값과 동일한 데이터 유형의 컴파일 타임 상수 값이어야합니다.

아래에서 (로컬 인스턴스로 메소드에서 또는 클래스에서 정적 변수로 정적 추가) 인스턴스 변수를 선언하십시오.

final String color1 = "Red";

static final String color2 = "Green";

switch (myColor) { // myColor is of data type String
    case color1:
    //do something here with Red
    break;
    case color2:
    //do something with Green
    break;
}

이 코드는 color1클래스 / 인스턴스 변수이고 로컬 변수 가 아닌 경우 컴파일 되지 않습니다. color1정적 최종으로 정의 된 경우 컴파일 된 다음 정적 최종 변수가됩니다.

컴파일하지 않으면 다음과 같은 오류가 발생합니다

error: constant string expression required

-7

키워드 "const"는 변수가 ROM에 저장되어 있음을 의미합니다 (마이크로 프로세서 포함). 컴퓨터에서 변수는 어셈블리 코드의 RAM 영역에 저장됩니다 (RAM 만 읽기). 변수가 쓰기 가능한 RAM에 없다는 것을 의미합니다 : 정적 메모리, 스택 메모리 및 힙 메모리.

키워드 "final"은 변수가 쓰기 가능한 RAM에 저장된다는 것을 의미하지만 변수가 한 번만 변경된다는 것을 컴파일러에 알 수 있습니다.

//in java language you can use:
static final int i =10;
i =11; //error is showed here by compiler

//the same in C++ the same as follows
int i =10;
const int &iFinal = i;

iFinal = 11; //error is showed here by compiler the same as above

"const"는 성능이 좋지 않기 때문에 Java는 사용하지 않습니다.

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