2013-10-23 4 views
0

Java 개념을 C++로 변환하는 데 도움이 필요합니다.C++에서 함수 선언을 찾는 방법

Java에서는 클래스를 만들고 메서드 (함수)를 제공 할 때 원하는 클래스 인스턴스에서 제대로 호출 할 수 있도록 해당 클래스에서 함수를 정의해야합니다. 예를 들어, Employee 클래스에서는 salaryRaise(int amount) 메서드를 선언하고 정의합니다. Employee 객체가 객체를 사용하려고 할 때마다 Employee.salaryRaise(i)을 호출하고 Java는 정확히 어디에서 찾을 수 있는지 - Employee 클래스에서 호출합니다.

C++에서 함수는 .h 개의 파일에 선언 된 다음 다른 위치에서 정의됩니다. 컴파일러는이 방법을 찾는 위치를 어떻게 알 수 있습니까?

+0

샘플 코드가 없으면 질문이 전혀 없습니다. 함수는 .ht로 선언되고, .cpp 파일로 작성되며, 호출하는 변수에는 모든 관련 유형이 있으며, 컴파일러는 모든 참조를 해석합니다. 뭐가 문제 야? – abelenky

+0

이 질문 (및 기타 매우 기본 질문)은 초보자 C++ 서적에 대한 답변을 제공합니다. [여기] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) 및 [여기] (http://stackoverflow.com/questions/194812/list-list- 자유 - 이용 - 프로그래밍 - 프로그래밍 서적). – JBentley

+0

자바와 같은 방식입니다. 링커가 해결합니다. 특정 클래스에 있다는 것을 알고 있기 때문에 함수가 어디에 메모리에 있는지 알 수있는 것은 아닙니다. 그래서 런타임에 이름을 메모리 위치로 변환해야합니다. 이것은 런타임 링커에 의해 수행됩니다. 주 : Java에서는 클래스 로더가 개념 레벨에서이 작업을 수행합니다. –

답변

2

을 반환 할 수 있습니다. h 파일에 저장되고 다른 곳에서 정의됩니다. 컴파일러는이 방법을 어디에서 찾을 수 있는지 어떻게 알 수 있습니까?

메소드의 정의를 제공 할 때 찾을 위치를 알려주기 때문에.

가상의 헤더 파일 고려 :

class Gizmo 
{ 
public: 
    bool Foo(); 
}; 

이제 우리는 또 다른 CPP 파일에 위의 Foo 방법을 정의합니다 :

여기
bool Gizmo::Foo() 
{ 
    return true; 
} 

은 위의 정의를 가지고있는 부연 대화의 :

좋습니다. bool을 반환하는 함수를 정의하고 있습니다. 함수는 Gizmo 클래스의 일부이며 함수의 이름은 Foo입니다. 이 함수는 매개 변수를 사용하지 않습니다. 함수의 정의는 다음과 같습니다. return true.

범위 확인 토큰 ::은 포함하는 클래스의 이름과 함수 이름을 구분합니다.

당신이 떠난 경우 Gizmo:: 비트 아웃, 대신 쓴 :

bool Foo() 
{ 
    return true; 
} 

를 사용해서 아직도 그것을 정의하는 대신 지금은 매개 변수를 사용하지 않는 및 부울을 반환하지만 Foo라는 이름의 함수를 정의 할 것 Gizmo의 일부가 되려면 자신의 것으로 정의해야합니다. 소위 "자유 기능"또는 "전역 기능". 이것은 정상적으로 컴파일되지만 어딘가 다른 코드가 Gizmo::Foo()을 사용하려고하면 "해결되지 않은 외부"링커 오류가 발생합니다.

+0

답변 주셔서 감사하지만 아직도 완전히 이해하지 못합니다. 'DooHickey' 클래스가'Antique' 클래스에서 정의 된'Gizmo :: Foo()'메소드를 호출하면 어떻게 프로그램이 정의를 찾습니까? 어디서나 포인터가 없습니다! C++은 정의를 찾기 위해 메소드가 호출 될 때마다 어디에서나 검색해야합니까? – CodyBugstein

1
당신이 :: 다음에 클래스 이름으로 몸과 다음 메소드 선언 결정 ++ C에서

:

class Employee 
{ 
    void salaryRaise(int amount); // Now, compiler knows this method belongs to 
           // the class Employee 
}; 

는 그런 다음 몸 정의 할 수 있습니다 : 오브젝트 파일을 생성

void Employee::salaryRaise(int amount) // Now, compiler knows everything about 
{ ^^^^^^^^^^      // definition of the method 
} 

을 (그리고 실행 가능한 바이너리를), 컴파일러 (실제로는 링커)에 .cpp 개의 파일을 전달해야합니다. 따라서 컴파일러는 모든 것을 볼 수 있습니다.

+0

하지만 본문은 모든 .cpp 파일에있을 수 있습니다. – CodyBugstein

+0

예, 링크 단계에서 관련 .cpp 파일을 컴파일러에 전달해야하며 컴파일러에서이를 사용해야합니다. – deepmax

+0

그래서 클래스의 다양한 메소드에 대한 정의를 무제한 파일 수에 분산시킬 수 있습니까? 그게 무슨 말이야? 특히 클래스 파일의 모든 클래스 메소드를 찾을 수 있다는 것을 알고있는 Java에서 왔습니다. – CodyBugstein

3

컴파일러가 소스를 바이너리로 변환하면 대개 클래스의 멤버 함수를 포함하는 중간 파일 (객체 파일이라고도 함)을 빌드합니다.

연결시 중간 파일이 기계어로 번역됩니다. 그 때 사용 된 모든 멤버 함수를 해결할 수 있으면 모두 좋다. 그렇지 않으면 연결 오류가 발생한다.

이렇게하면 멤버 함수의 정의를 프로젝트의 아무 곳에 나 배치 할 수 있습니다. 링커가 필요한 것을 찾으면 이진을 빌드 할 수 있습니다. 그러나이 접근법은 클래스 목적/기계공에 대한 인간의 읽기/이해를 향상시킬 것이므로 조언하지 않습니다.

+0

설명해 주셔서 감사합니다. 메소드 정의가 어디 에나 흩어져있을 수 있습니다. 그래서 본질적으로'MaintenanceSupplies' 클래스 안에'Employee' 클래스의'raiseSalary()'메소드에 대한 정의를 넣을 수 있습니까? 와우 나는 이것이 나빠질 것을 알 수있다. – CodyBugstein

+1

@Imray - 참으로. 이것이 바로 C++ 이후에 설계된 Java가 클래스와 관련된 모든 코드를 하나의 파일로 저장해야하는 이유입니다. – Attila

6

이것은 실제로 컴파일러가 아니라 링커의 역할입니다. 컴파일러는 아직 정의되지 않은 심볼을 참조하는 함수를 호출합니다. 그런 다음 링커는 다른 번역 단위를 가져 와서 심볼을 이름으로 해석합니다 (즉, 네임 스페이스, 인수 유형으로 추가 정보를 인코딩하는 변형 된 이름 ...)

2

컴파일러에는 일반적으로 컴파일 단계가 있습니다 연결 단계. 컴파일 단계에서는 소스 파일을 오브젝트 파일로 컴파일합니다. 연결 단계는 오브젝트 파일을 수집하고 실행 가능 이미지를 작성합니다. 연결 단계에서 컴파일 단계에서 해결되지 않은 기호가 해결됩니다. 이것은 Java와 C++ 모두별로 다르지 않습니다. 예를 들어, Java 클래스가 다른 Java 클래스에서 메소드를 호출하는 방법입니다.

4

헤더 (.h) 파일에 함수를 선언합니다. 그런 다음 해당 헤더 파일은 기능을 사용해야하는 다른 파일에서 #include을 가져옵니다. 컴파일러는 함수의 서명과 호출 방법을 알고 있기 때문에 컴파일러를 만족시킵니다.

이 함수는 소스 (.cpp) 파일에 정의됩니다. 소스 파일에는 자체 헤더 파일이 포함되어 있으므로 컴파일 할 때 해당 함수의 전체 컴파일 된 코드가 포함 된 객체 파일로 끝납니다.

링커는 함수를 호출 한 코드의 일부 (즉, 헤더를 포함하는 파일)와 해당 함수의 실제 코드를 연결합니다. 예와

편집 :

Foo.h :

#ifndef FOO_H 
#define FOO_H 

class Foo 
{ 
public: 
    int fooFunction(double a); 
}; 

#endif 

foo.cpp의 :

#include "Foo.h" 

int Foo::fooFunction(double a) 
{ 
    // Function definition 
    return 1; 
} 

Foo.cpp 컴파일은 완전한 정의 FO를 포함 Foo.obj를 생성 r fooFunction. 여태까지는 그런대로 잘됐다.

Bar.h :

#ifndef BAR_H 
#define BAR_H 

#include "Foo.h" 

class Bar 
{ 
public: 
    void barFunction(); 
}; 

#endif 

Bar.cpp는 :

#include "Bar.h" 

void Bar::barFunction() 
{ 
    Foo foo; 
    int returnValue = foo.fooFunction(2.0); 
} 

Bar.cpp 차례로 Foo.h 포함 Bar.h 포함한다. 따라서 Bar.cpp이 사전 처리되면 Foo::fooFunction에 대한 선언이 파일의 맨 위에 삽입됩니다. 따라서 문 int returnValue = foo.fooFunction(2.0);이 컴파일되면 컴파일러는 반환 값 (int)의 유형을 알고 매개 변수의 유형 (double 및 암시 적 this 포인터)을 알고 있기 때문에 fooFunction을 호출하는 기계 명령어를 내보내는 방법을 알고 있습니다 foo 개체의 경우). 함수 정의가 제공되지 않았기 때문에 함수는 인라인되지 않습니다 (인라인이란 함수의 전체 코드가 호출되는 지점으로 복사됨을 의미합니다). 대신 함수의 메모리 주소를 가리키는 포인터가 사용됩니다. 포인터가 사용 중이기 때문에 컴파일러는 정의를 신경 쓰지 않습니다. 알아야 할 것은 모두 입니다. "매개 변수 A와 B를 사용하여 메모리 위치 Y에서 함수 X를 호출해야하고 크기가 int이어야합니다. 메모리 섹션에 반환 값을 저장할 준비가되어 있고 그 주소의 코드가 ""함수를 수행하는 방법을 알고 있다고 가정합니다. 그러나 컴파일러는 함수 정의가 별도의 .cpp 파일에 있고 별도의 컴파일 작업 AKA 번역 단위의 일부이기 때문에 사전에 해당 함수의 주소를 알 수있는 방법이 없습니다.

그게 링커가 들어오는 곳입니다. 모든 번역 단위가 컴파일되면 (임의의 순서 일 수 있음) 링커는 Bar.cpp의 컴파일 된 코드로 돌아가서 fooFunction의 컴파일 된 정의는 Bar.cpp에서 호출되어 컴파일 된 코드를 완전히 실행 가능하게 만듭니다.

+0

여기 내가 혼란스러워하는 곳이있다. 좋아, 컴파일러를 만족 시키려면''.h' 파일에 "foo (int i)'"라는 함수를 보라. 이제 ClassA, ClassB 등 어디에서든지 해당 함수를 호출 할 수 있습니다. 그러나 함수의 의미는 무엇입니까? 정의되는 위치는 무엇입니까 ?? ClassA에서 정의 된 경우 ClassB에서 호출하면 어떻게됩니까? ClassB는'.h' 만 확인할 수 있지만'.h'는 ClassA의 정의에 대한 참조를 가지고 있지 않습니다. 이것은 내가 잃어버린 곳입니다. 당신의 설명에서 뭔가가 빠졌습니다. 당신은 명확히 할 수 있습니까? – CodyBugstein

+0

@imray 귀하의 코멘트에 대한 편집을 참조하십시오. – JBentley

+0

@imray 몇 가지 오타를 수정하고 몇 가지 점을 명확하게 (재클림) 재 편집했습니다. – JBentley

0

헤더 파일에서 프로토 타입/전달 클래스를 이와 같이 선언합니다.

class Foo 
{ 
private: 
    int m_Fooint; 
    int m_Fooint2; 
public: 
    Foo(int a, int b); 
    int getFooTotal(); 
}; 

그런 다음 생성자와 소멸자 게다가이

Foo::Foo(int a, int b) // prototypes names don't have to be the same 
{ 
    Foo::m_Fooint = a; 
    Foo::m_Fooint2 = b; 
} 

int Foo::getFooTotal() 
{ 
    return Foo::m_Fooint + Foo::m_Fooint2; 
} 

같은 멤버 함수를 정의하는 것입니다, 당신은 데이터 형식이 필요합니다. 무효이고 아무것도 반환하지 않더라도.

그래서 당신은

float Foo::getSomeFloat(); 

또는

double Foo::getSomeDouble(); 

같은 뭔가가있을 수 있습니다 또는 당신은 객체를 C++, 함수에 선언에서

OtherClass Foo::getOtherClassObject(); 
관련 문제