2009-06-07 5 views
27

먼저 C와 C++ 모두에서 상당한 양의 경험을 얻었습니다. 그러나 C에서 새 프로젝트를 시작하고 있으며 오랫동안 (C# 및 C++) 객체 지향 언어로 작업하여 절차 언어로 기능을 캡슐화하는 효과적인 방법을 생각해 내는데 어려움을 겪고 있습니다. 내 첫번째 생각은 단순히 내 OO 지식을 후퇴하고 그것을 같은 구조했다 :C 프로그램을 효과적으로 구성하는 방법

struct Foo 
{ 
    int x; 
    char *y; 
}; 

struct Foo *new_Foo() 
{ 
    return (struct Foo *)malloc(sizeof(struct Foo)); 
} 

void Foo_member_function(struct Foo *foo, int z) 
{ 
    foo->x = z;  
} 

을하지만 그냥 가난한 남자의 OO 것을 언급하지 않기 위하여 C의 정신에 지루하고 반대로 보인다.

이 프로그램은 궁극적으로 상당한 규모가 될 것이므로 좋은 디자인 조직에서 시작하는 것이 중요합니다. C 언어의 개발로 수년간 유지 보수를위한 코드를 가장 잘 구조화하는 방법에 대한 특정 디자인 패턴이 개발되었다고 생각합니다. 함수형 프로그래밍과 마찬가지로, 절차 형 프로그래밍에는 깨끗하고 공정한 패러다임이 필요합니다.

관련 기사 및 서적에 대한 포인터도 허용됩니다.

+0

그들은 모두 유용한 맛있는 가벼운 음식을 가지고 있기 때문에 하나의 대답만을 골라내는 것이 싫지만 불투명 포인터 참조는 아마도 내가 알지 못했던 가장 유용한 것이었을 것입니다. 감사! – HVS

답변

15

이것은 상당히 정상적이고 합리적인 방법입니다. 그러나 헤더 파일에 구조체 레이아웃을 드러내지 않도록하십시오. 그러면 구현 방식에 유연성을 제공하고 종속성을보다 잘 관리 할 수 ​​있습니다.

자세한 내용은 Opaque pointer을 참조하십시오.

+1

은 HWND와 native win32 C api를 생각 나게합니다 – bobobobo

11

당신이 제안하는 것은 내가 그런 일을했던 날에 내가 항상 C 프로그램을 다시 쓰는 방법이다. 나는 그것이 "가난한 사람을 괴롭히는 사람"이라고 생각하지 않는다. 나는 합리적인 절차 프로그래밍 연습이라고 생각한다.

나는 당신의 C 코드에 대해 몇 가지를 관찰 할

: 당신은 코드에 걸쳐 '구조체'키워드를 분산 할 필요가 없습니다 구조체 정의와

  • 사용 형식 정의는
  • 만 사용하는 경우 캐스트 실제로 필요합니다 - malloc()에서 반환 값에 대한 캐스트가 필요하지 않습니다.
+0

좋은 조언. 내가 "가난한 OO"의 의미는 매우 제한된 OO (즉, 다형성, 캡슐화 없음 등)이었습니다. – HVS

+1

하지만 typedef는 Linux kernal crew를 포함하여 일부 사람들에게 나쁜 습관으로 간주된다는 것을 알고 있습니까? – temp2290

1

C는 저급 언어 였고 관련하여 코드에 따라 데이터 구조를 구성하는 것이 매우 유용합니다 기능 및 모듈.

데이터 개체를 만들 때마다 typedef와 열거 형을 사용하는 것이 좋습니다. 필요에 따라 매크로 또는 정적 함수를 사용하여 초기화, 할당 및 '파괴'하십시오.

3

흠 ... 이름 지정 규칙을 사용하는 데 사용되었습니다 ... Ergo : str *은 일반적인 데이터 구조를 사용합니까? 어쩌면 C# 구문과 s /./_/ g를 사용할 수 있을까요?

  • foo_constructor
  • foo_destructor
  • foo_someMethod
  • foo_someMethod2 //는 ANSI C
  • foo_otherMethod

에는 오버로딩되지 않습니다 ... 더 상속이되지 않는다. ..

  • foo2_constructor
  • foo2_destructor
  • foo2_someMethod // 더 다형성

그러나 밝은면에 볼이되지 않습니다 ... 당신이 포인터에 포인터 대를 사용할 수 있습니다 pointer-to-function-returning-a-pointer-to-pointer-int! 오, 기쁨!

가장 좋은 조언은 Java (및 추론 C#)의 교훈을 배우고 라이브러리에 부작용이 없도록 구조화하는 것입니다. more typdefs == 덜 두통 ... 그리고 운동을하는 방법 이 세이 지의 조언을 따르십시오 ;-)

환호. 키이스.

+0

"부작용"은 정적 변수, 전역 변수 등을 의미한다고 가정합니까? 분명히 라이브러리는 그들이 수정하는 "객체"에 부작용을 줄 것입니다. – HVS

+0

일반적으로 일부 상태를 업데이트하기 위해 기존 상태를 변경하는 대신 새 상태를 반환 할 수 있습니다. 이는 기능 프로그래밍과 일치하며 데이터 흐름 종속성을 훨씬 명확하고 쉽게 따라 할 수 있습니다. – none

2

C 프로그램을 작성하는 것은 꽤 합리적인 방법입니다. 리눅스 커널이라고 불리는 또 다른 큰 응용 프로그램이 있습니다. 일부 거의 OO-기능이 있습니다에 사용 : 캡슐화 구조체에

  • 구조체 및 운영을처럼 당신의 예제에서 기본 구조체에
  • 포인터를 가난한 사람의 상속의 형태로 - 당신은 의 부하를 찾을 수 있습니다 참조는
1

나는 위의 제안에 동의 템플릿 프로그래밍을위한 대체 기능을 생성 할 수있다

  • 매크로에 kobject 구조체입니다. C 언어로 프로그램하고 싶다면 .. 최선을 다하고 있습니다.

    물론,이 선언과 자동 생성을위한 프리 프로세서를 작성할 수 있습니다. 아마도 "클래스"선언을 사용할 수 있습니다. .. 멤버 함수가되고 싶은 함수를 클래스 내에 두어라.

    하지만 우리가 가진 것은 간단한 C++에서 C 컴파일러이다. 왜 C++로 프로그램하고, 진짜 C++ 컴파일러를 사용하고, 깨끗한 인터페이스를 사용하고, C++ 코드를 C 코드와 링크시키는 것이 좋을까요? C와 C++로 코딩해야하는 이유는 무엇입니까? 또는 필요한 경우 컴파일러에서 C 코드를 생성하고 필요한 다른 것과 함께 출력 C 코드를 컴파일하십시오.

  • +1

    저는 지난 몇 년 동안 엄청나게 향상되었지만 (Boost는 훌륭한 라이브러리입니다) C++의 팬이 아닙니다. 그 외에도이 프로젝트의 일부는 C를 선택하는 이유 중 하나 인 상당히 낮은 수준입니다. 다른 하나는 오픈 소스가 될 수 있으며 가능한 한 유연하게 유지하고자하는 것입니다. 나는 C++로 할 수 있었지만 그것이 가치 있다고 생각되는 문제를 야기 할 수있다. – HVS

    +1

    모든 기능을 사용할 필요는 없습니다. 클래스, 메소드, 생성자, 소멸자 등 매우 간단한 하위 세트 만 사용하면됩니다. 나머지는 표준으로 유지하십시오. c. 오픈 소스 릴리스의 경우 C++에서 C 컴파일러를 실행하고 C 코드를 배포 할 수 있습니다. –

    +0

    C는 우리가 낮은 수준에서하는 일이며, C++은 Linux 환경 시스템에 거의 가치가 없습니다. 당신도 똑같이하거나, C로 천천히 가져 가거나, 여전히 완전히 컴파일되기를 원하는 물건에 golang 같은 현대 언어를 사용합니다. C++은 코드를 넘어서는 개발자이며, 이는 그 정신과는 대조적입니다. – TechZilla

    0

    나는 라이브러리가 C에 있어야하지만, OO 기능의 일부 형태를 원한다. 나는 조금 더 자세하게 이것과 비슷한 것을하고있다.

    struct klass { 
        char * value; 
    
        void (*set_value) (struct klass *, const char *); 
        void (*destroy) (struct klass *); 
    }; 
    
    static void 
    klass_method_set_value (struct klass * k, const char * value) { 
        if (k->value == NULL) { 
        } 
    } 
    
    static void 
    klass_object_desetroy (struct klass * k) { 
        free (k); 
        k = NULL; 
    } 
    
    static void 
    klass_method_destroy (struct klass * k) { 
        klass_object_destroy (k); 
    } 
    
    static struct klass * 
    klass_object_init (void) { 
        struct klass * obj = (struct klass *) malloc (sizeof (struct klass*)); 
    
        /* members */ 
        obj->value = NULL; 
    
        /* methods */ 
        obj->set_value = klass_method_set_value; 
        obj->destroy = klass_method_destroy; 
        return obj; 
    } 
    
    struct klass * 
    klass_new (void) { 
        return klass_object_init(); 
    } 
    

    내가 잘못하면 용서해주십시오. 그것을 조금 빨리 썼다.

    +0

    그래, 그게 내가 피하고 싶었던 종류 야. Stroustrup이 처음으로 C++ 컴파일러를 코딩 한 것을 기본적으로 들었습니다. – HVS

    관련 문제