임베디드 프로젝트에서 작업하면서 모든 C로 한 번 작업을 시도했지만 참을 수 없었습니다. 너무 장황해서 아무것도 읽기가 어려웠습니다. 또한 내가 작성한 내장 컨테이너에 최적화 된 것이 마음에 들었습니다.이 컨테이너는 훨씬 덜 안전하고 #define블록 을 수정하기가 더 어렵습니다 .
C ++의 코드는 다음과 같습니다.
if(uart[0]->Send(pktQueue.Top(), sizeof(Packet)))
pktQueue.Dequeue(1);
다음으로 바뀝니다.
if(UART_uchar_SendBlock(uart[0], Queue_Packet_Top(pktQueue), sizeof(Packet)))
Queue_Packet_Dequeue(pktQueue, 1)
많은 사람들이 아마 괜찮다고 말 하겠지만 한 줄에 두 번 이상의 "방법"호출을해야한다면 우스꽝스러워집니다. 두 줄의 C ++는 80 자의 줄 길이 제한으로 인해 C의 다섯 줄로 바뀝니다. 둘 다 동일한 코드를 생성하므로 대상 프로세서가 신경 쓰지 않습니다!
한 번은 (1995 년) 다중 프로세서 데이터 처리 프로그램을 위해 많은 C를 작성하려고했습니다. 각 프로세서에 자체 메모리와 프로그램이있는 종류입니다. 공급 업체에서 제공 한 컴파일러는 C 컴파일러 (일종의 HighC 파생물) 였고 라이브러리는 폐쇄 된 소스 였기 때문에 GCC를 사용하여 빌드 할 수 없었으며 API는 프로그램이 주로 초기화 / 프로세스가 될 것이라는 사고 방식으로 설계되었습니다. / 종결 다양성, 그래서 프로세서 간 통신은 기껏해야 초보적이었습니다.
포기하기 약 한 달 전에 cfront 사본을 찾았습니다. C ++를 사용할 수 있도록 makefile에 해킹했습니다. Cfront는 템플릿도 지원하지 않았지만 C ++ 코드는 훨씬 더 명확했습니다.
일반 형식이 안전한 데이터 구조 (템플릿 사용).
C가 템플릿에 가장 가까운 것은 다음과 같은 많은 코드로 헤더 파일을 선언하는 것입니다.
TYPE * Queue_##TYPE##_Top(Queue_##TYPE##* const this)
{ }
그런 다음 다음과 같이 가져옵니다.
#define TYPE Packet
#include "Queue.h"
#undef TYPE
처음 unsigned char만들지 않는 한 복합 유형 (예 :의 대기열 없음 ) 에는 작동하지 않습니다 typedef.
아, 그리고이 코드가 실제로 어디에도 사용되지 않는다면 구문 상 올바른지조차 알지 못합니다.
편집 : 한 가지 더 : 코드 인스턴스화 를 수동으로 관리 해야 합니다. "템플릿"코드가 모두 인라인 함수 가 아닌 경우 , 링커가 "다중 Foo 인스턴스"오류를 뱉어 내지 않도록 한 번만 인스턴스화되도록 일부 제어를해야합니다. .
이렇게하려면 헤더 파일의 "구현"섹션에 인라인되지 않은 항목을 넣어야합니다.
#ifdef implementation_##TYPE
#endif
그런 다음 템플릿 변형 당 모든 코드의 한 곳에서 다음 을 수행해야합니다.
#define TYPE Packet
#define implementation_Packet
#include "Queue.h"
#undef TYPE
또한이 구현 섹션 은 다른 헤더 파일에 템플릿 헤더 파일을 포함 할 수 있지만 나중에 파일 에서 인스턴스화해야하기 때문에 표준 / / litany 외부 에 있어야 합니다.#ifndef#define#endif.c
네, 추악하게 빠르게됩니다. 그래서 대부분의 C 프로그래머는 시도조차하지 않습니다.
RAII.
특히 여러 리턴 포인트가있는 함수에서, 예를 들어 각 리턴 포인트에서 뮤텍스를 해제하는 것을 기억할 필요가 없습니다.
음, 예쁜 코드를 잊고 (함수의 끝 제외) 모든 반환 지점에 익숙해 인 goto들 :
TYPE * Queue_##TYPE##_Top(Queue_##TYPE##* const this)
{
TYPE * result;
Mutex_Lock(this->lock);
if(this->head == this->tail)
{
result = 0;
goto Queue_##TYPE##_Top_exit:;
}
Queue_##TYPE##_Top_exit:
Mutex_Lock(this->lock);
return result;
}
일반적으로 소멸자.
즉, MyClass에 대해 d' tor를 한 번 작성하면 MyClass 인스턴스가 MyOtherClass의 멤버 인 경우 MyOtherClass는 MyClass 인스턴스를 명시 적으로 초기화 할 필요가 없습니다. 해당 d' tor는 자동으로 호출됩니다.
객체 생성은 동일한 방식으로 명시 적으로 처리되어야합니다.
네임 스페이스.
그것은 실제로 고치기 쉬운 것 입니다. 모든 심볼에 접두사를 붙이기 만하면 됩니다 . 이것이 제가 이전에 이야기했던 소스 팽창의 주요 원인입니다 (클래스는 암시 적 네임 스페이스이기 때문입니다). C 사람들은 이것을 영원히 살았고 아마도 큰 문제가 무엇인지 알지 못할 것입니다.
YMMV