"정적"기능이란 무엇입니까?
문제는 주석에서 분명한 것처럼 c ++ 메소드가 아닌 일반 c 함수 에 관한 것 입니다. static
좋아, 나는 static
변수가 무엇인지 이해 하지만 static
함수 는 무엇 입니까?
그리고 왜 내가 함수를 선언하는 경우,의 말을 할 수 있다는 것입니다 void print_matrix
하자의 말에, a.c
(없이 a.h
) 및 포함 "a.c"
내가 얻을 - "print_matrix@@....) already defined in a.obj"
내가로 선언하는 경우,하지만 static void print_matrix
다음 컴파일?
업데이트 일을 정리하는 것만으로 .c
도 많은 사람들이 지적했듯이 포함 이 나쁘다는 것을 알고 있습니다. 난 그냥 일시적으로 빈 공간에 어떻게 main.c
내가 적절한으로하는 방법 그룹에 모든 기능의 더 나은 아이디어 때까지 .h
와 .c
파일을. 일시적인 빠른 솔루션입니다.
static
함수는 동일한 파일 (보다 정확하게 같은 변환 단위 )의 다른 함수에서만 볼 수있는 함수입니다 .
편집 : 생각하는 사람들을 위해, 질문의 저자는 '클래스 방법'을 의미한다고 생각합니다. 질문에 태그가 붙어 있기 때문에 C
그는 평범한 오래된 C 함수를 의미합니다. (C ++ / Java / ...) 클래스 메소드의 static
경우 클래스 자체에서이 메소드를 호출 할 수 있으며 해당 클래스의 인스턴스는 필요하지 않습니다.
C의 정적 함수와 C ++의 정적 멤버 함수에는 큰 차이가 있습니다. C에서 정적 함수는 변환 단위 (컴파일 된 오브젝트 파일) 외부에서 볼 수 없습니다. 다시 말해, 함수를 정적으로 만들면 범위가 제한됩니다. 정적 함수는 * .c 파일에 대해 "비공개"인 것으로 생각할 수 있습니다 (엄격히 정확하지는 않지만).
C ++에서 "정적"은 멤버 함수 및 클래스의 데이터 멤버에도 적용 할 수 있습니다. 정적 데이터 멤버는 "클래스 변수"라고도하며 비 정적 데이터 멤버는 "인스턴스 변수"입니다. 이것이 스몰 토크 용어입니다. 이는 클래스의 모든 객체가 공유하는 정적 데이터 멤버의 사본이 하나만있는 반면 각 객체에는 정적이 아닌 데이터 멤버의 고유 한 사본이 있습니다. 따라서 정적 데이터 멤버는 기본적으로 전역 변수, 즉 클래스 멤버입니다.
비 정적 멤버 함수는 정적 및 비 정적 클래스의 모든 데이터 멤버에 액세스 할 수 있습니다. 정적 멤버 함수는 정적 데이터 멤버에서만 작동 할 수 있습니다.
이것을 생각하는 한 가지 방법은 C ++ 정적 데이터 멤버와 정적 멤버 함수가 객체가 아니라 전체 클래스에 속한다는 것입니다.
C ++의 함수와 관련하여 static 키워드에는 두 가지 용도가 있습니다.
첫 번째는 함수가 내부 연결이있는 것으로 표시하여 다른 변환 단위에서 참조 할 수 없도록하는 것입니다. 이 사용법은 C ++에서 더 이상 사용되지 않습니다. 이름없는 네임 스페이스가이 사용법에 선호됩니다.
// inside some .cpp file:
static void foo(); // old "C" way of having internal linkage
// C++ way:
namespace
{
void this_function_has_internal_linkage()
{
// ...
}
}
두 번째 사용법은 클래스와 관련이 있습니다. 클래스에 정적 멤버 함수가있는 경우 함수는 클래스의 멤버이며 다른 멤버에 대한 일반적인 액세스 권한이 있지만 특정 객체를 통해 호출 할 필요는 없습니다. 다시 말해, 그 함수 내부에는 "this"포인터가 없습니다.
실행 가능한 최소 다중 파일 범위 예
여기 static
에서는 여러 파일에서 함수 정의 범위에 어떤 영향을 미치는지 설명 합니다.
ac
#include <stdio.h>
/* Undefined behavior: already defined in main.
* Binutils 2.24 gives an error and refuses to link.
* https://stackoverflow.com/questions/27667277/why-does-borland-compile-with-multiple-definitions-of-same-object-in-different-c
*/
/*void f() { puts("a f"); }*/
/* OK: only declared, not defined. Will use the one in main. */
void f(void);
/* OK: only visible to this file. */
static void sf() { puts("a sf"); }
void a() {
f();
sf();
}
main.c
#include <stdio.h>
void a(void);
void f() { puts("main f"); }
static void sf() { puts("main sf"); }
void m() {
f();
sf();
}
int main() {
m();
a();
return 0;
}
컴파일하고 실행하십시오.
gcc -c a.c -o a.o
gcc -c main.c -o main.o
gcc -o main main.o a.o
./main
산출:
main f
main sf
main f
a sf
해석
sf
각 파일마다 하나씩 두 개의 개별 기능이 있습니다- 단일 공유 기능이 있습니다
f
평소와 같이 범위가 작을수록 좋습니다. 가능하면 항상 함수를 선언하십시오 static
.
C 프로그래밍에서 파일은 종종 "클래스"를 나타내는 데 사용되며 static
함수는 클래스의 "비공개"메소드를 나타냅니다.
일반적인 C 패턴은 this
구조체를 첫 번째 "메서드"인수로 전달하는 것인데, 기본적으로 C ++이 수행하는 방식입니다.
그것에 대해 말하는 표준
C99 N1256 draft 6.7.1 "스토리지 클래스 지정자"는 "스토리지 클래스 지정자"라고 말합니다 static
.
6.2.2 / 3 "식별자 링크"는 다음을 static
의미합니다 internal linkage
.
객체 또는 함수에 대한 파일 범위 식별자 선언에 스토리지 클래스 지정자 정적이 포함되어 있으면 식별자에 내부 연결이 있습니다.
그리고 6.2.2 / 2는 internal linkage
우리 예제에서와 같이 동작 한다고 말합니다 :
전체 프로그램을 구성하는 변환 단위 및 라이브러리 세트에서 외부 링크가있는 특정 식별자의 각 선언은 동일한 객체 또는 함수를 나타냅니다. 하나의 변환 단위 내에서 내부 연결이있는 식별자의 각 선언은 동일한 객체 또는 함수를 나타냅니다.
여기서 "번역 단위"는 사전 처리 후 소스 파일입니다.
GCC가 ELF (Linux)를 위해 어떻게 구현합니까?
와 STB_LOCAL
바인딩.
우리가 컴파일하면 :
int f() { return 0; }
static int sf() { return 0; }
다음과 같이 심볼 테이블을 분해하십시오.
readelf -s main.o
출력에는 다음이 포함됩니다.
Num: Value Size Type Bind Vis Ndx Name
5: 000000000000000b 11 FUNC LOCAL DEFAULT 1 sf
9: 0000000000000000 11 FUNC GLOBAL DEFAULT 1 f
바인딩은 그들 사이의 유일한 중요한 차이점입니다. 섹션에 Value
대한 오프셋 일 뿐이 .bss
므로 차이가있을 것으로 예상합니다.
STB_LOCAL
http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html 의 ELF 사양에 설명되어 있습니다 .
STB_LOCAL 로컬 심볼은 해당 정의가 포함 된 오브젝트 파일 외부에 표시되지 않습니다. 동일한 이름의 로컬 기호가 서로 방해하지 않고 여러 파일에 존재할 수 있습니다
표현하기에 완벽한 선택 static
입니다.
정적이없는 함수는 STB_GLOBAL
이며 사양은 다음과 같습니다.
링크 편집기가 재배치 가능한 여러 오브젝트 파일을 결합 할 때 동일한 이름을 가진 STB_GLOBAL 기호의 다중 정의를 허용하지 않습니다.
정적이 아닌 여러 정의에서 링크 오류와 일치합니다.
로 최적화를 크랭크 -O3
하면 sf
심볼이 심볼 테이블에서 완전히 제거됩니다. 어쨌든 외부에서는 사용할 수 없습니다. TODO 최적화가 없을 때 심볼 테이블에 정적 함수를 유지하는 이유는 무엇입니까? 그들은 무엇이든 사용할 수 있습니까?
또한보십시오
- 변수와 동일 : https://stackoverflow.com/a/14339047/895245
extern
의 반대static
이며 함수는 이미extern
기본적으로 사용됩니다. 소스 파일간에 변수를 공유하기 위해 extern을 어떻게 사용합니까?
C ++ 익명 네임 스페이스
C ++에서는 정적 대신 익명 네임 스페이스를 사용하여 유사한 효과를 얻을 수 있지만 유형 정의를 숨 깁니다. 이름이없는 / 익명 네임 스페이스와 정적 함수
다음은 일반 C 함수에 관한 것입니다. C ++ 클래스에서 수정 자 '정적'은 다른 의미를 갖습니다.
파일이 하나 뿐인 경우이 수정자는 아무런 차이가 없습니다. 파일이 여러 개인 대규모 프로젝트에서는 차이점이 있습니다.
C에서는 모든 "모듈"(sample.c와 sample.h의 조합)이 독립적으로 컴파일 된 후 컴파일 된 모든 객체 파일 (sample.o)이 링커에 의해 실행 파일에 함께 연결됩니다.
기본 파일에 포함 된 여러 파일이 있고 그 중 두 개는 편의상 내부에서만 사용되는 기능을 가지고 있다고 가정 해 봅시다 add(int a, b)
. 컴파일러는 두 모듈에 대한 객체 파일을 쉽게 만들 수 있지만 링커는 오류를 발생시킵니다. 동일한 이름을 가진 두 개의 함수를 찾고 어떤 함수를 사용해야하는지 알지 못합니다 (링크가없는 경우에도 다른 곳에서 사용되지 않고 자체 파일에서 사용되기 때문에).
이것이 바로 내부 정적 함수 인이 함수를 만드는 이유입니다. 이 경우 컴파일러는 링커에 대해 일반적인 "이 링크를 연결할 수 있습니다"플래그를 만들지 않으므로 링커에서이 기능을 볼 수없고 오류가 발생하지 않습니다.
첫째 : .cpp
다른 파일에 파일 을 포함시키는 것은 일반적으로 나쁜 생각입니다. 다음 과 같은 문제가 발생합니다 :-) 일반적인 방법은 별도의 컴파일 단위를 만들고 포함 된 파일의 헤더 파일을 추가하는 것입니다.
둘째 :
C ++에는 혼란스러운 용어가 있습니다. 댓글에서 지적 할 때까지 그것에 대해 알지 못했습니다.
a) static functions
-C에서 상속되었으며 여기에서 말하는 내용. 수업 외 정적 함수 는 현재 컴파일 단위 외부에서는 보이지 않으므로 a.obj에는 복사본이 있고 다른 코드에는 독립적 인 복사본이 있습니다. (여러 코드 사본으로 최종 실행 파일을 블로 팅).
b) static member function
-정적 메소드 인 Object Orientation 용어 . 수업 안에 살고 있습니다. 이것을 객체 인스턴스가 아닌 클래스로 호출합니다.
이 두 가지 정적 함수 정의는 완전히 다릅니다. 조심하십시오-여기에 용이 있습니다.
정적 함수 정의는이 기호를 내부로 표시합니다. 따라서 외부에서 링크하는 것은 보이지 않지만 동일한 컴파일 단위, 일반적으로 동일한 파일의 함수에만 표시됩니다.
정적 함수는 클래스 인스턴스와 달리 클래스 자체에서 호출 할 수있는 함수입니다.
예를 들어 비정 적은 다음과 같습니다.
Person* tom = new Person();
tom->setName("Tom");
이 메소드는 클래스 자체가 아닌 클래스의 인스턴스에서 작동합니다. 그러나 인스턴스 없이도 작동 할 수있는 정적 메서드를 사용할 수 있습니다. 이것은 때때로 팩토리 패턴에서 사용됩니다 :
Person* tom = Person::createNewPerson();
정적 함수에 대한 답변은 언어에 따라 다릅니다.
1) C와 같은 OOPS가없는 언어에서는 정의 된 파일 내에서만 함수에 액세스 할 수 있습니다.
2) C ++과 같은 OOPS 언어에서는 인스턴스를 만들지 않고 클래스에서 함수를 직접 호출 할 수 있습니다.
사소한 의미 : 정적 함수는 변환 단위에 표시되며, 대부분의 실제 경우에는 함수가 정의 된 파일입니다.받는 오류는 일반적으로 하나의 정의 규칙 위반이라고합니다.
표준은 아마도 다음과 같이 말합니다.
"모든 프로그램에는 해당 프로그램에서 사용되는 모든 비 인라인 함수 또는 객체에 대한 정의가 정확히 하나만 있어야하며 진단이 필요하지 않습니다."
이것이 정적 함수를 보는 C 방식입니다. 그러나 이것은 C ++에서 더 이상 사용되지 않습니다.
또한 C ++에서는 멤버 함수를 정적으로 선언 할 수 있습니다. 이것들은 대부분 메타 함수입니다. 즉, 특정 객체의 동작 / 상태를 설명 / 수정하지 않지만 전체 클래스 자체에 작용합니다. 또한 이는 정적 멤버 함수를 호출하기 위해 오브젝트를 작성할 필요가 없음을 의미합니다. 또한 이는 해당 함수 내에서만 정적 멤버 변수에만 액세스 할 수 있음을 의미합니다.
Parrot의 예제에 프로그램의 수명 기간 동안 단일 객체를 가져 오거나 사용하기 위해 이러한 종류의 정적 멤버 함수를 기반으로하는 Singleton 패턴을 추가했습니다.
참고 URL : https://stackoverflow.com/questions/558122/what-is-a-static-function
'Programming' 카테고리의 다른 글
IllegalStateException : ViewPager를 사용하여 onSaveInstanceState 후에이 조치를 수행 할 수 없습니다. (0) | 2020.02.15 |
---|---|
java.util.Date를 java.time.LocalDate로 변환 (0) | 2020.02.15 |
라이브 MySQL 쿼리를 보려면 어떻게해야합니까? (0) | 2020.02.15 |
파이썬을 사용하여 CPU 수를 찾는 방법 (0) | 2020.02.15 |
ReSharper는 프로젝트 빌드시에도 "심볼을 확인할 수 없습니다" (0) | 2020.02.15 |