IT TIP

헤더없이 (반복적 인 함수 선언) C ++ 코드를 작성할 수 있습니까?

itqueen 2020. 12. 26. 16:20
반응형

헤더없이 (반복적 인 함수 선언) C ++ 코드를 작성할 수 있습니까?


함수 선언을 두 번 (헤더) 작성하지 않아도 컴파일 할 때 동일한 확장 성, 디버깅의 명확성 및 C ++로 프로그래밍 할 때 디자인의 유연성을 유지할 수있는 방법이 있습니까?


Lzz를 사용하십시오 . 단일 파일을 사용하여 올바른 위치에 모든 선언 / 정의와 함께 .h 및 .cpp를 자동으로 생성합니다.

Lzz는 매우 강력하며 템플릿, 전문화 등을 포함하여 전체 C ++ 구문의 99 %를 처리합니다.

150120 업데이트 :

최신 C ++ '11 / 14 구문은 Lzz 함수 본문 내에서만 사용할 수 있습니다.


C를 쓰기 시작했을 때도 같은 느낌이어서 이것도 살펴 보았습니다. 대답은 예, 가능하고 아니오, 원하지 않는다는 것입니다.

먼저 그렇습니다.

GCC에서는 다음을 수행 할 수 있습니다.

// foo.cph

void foo();

#if __INCLUDE_LEVEL__ == 0
void foo() {
   printf("Hello World!\n");
}
#endif

이것은 의도 된 효과를 가지고 있습니다. 헤더와 소스를 모두 포함하고 링크 할 수있는 하나의 파일로 결합합니다.

그런 다음 아니오 :

컴파일러가 전체 소스에 액세스 할 수있는 경우에만 작동합니다. 배포하고 싶지만 비공개 소스를 유지하는 라이브러리를 작성할 때는이 트릭을 사용할 수 없습니다. 전체 .cph 파일을 배포하거나 .lib와 함께 사용할 별도의 .h 파일을 작성해야합니다. 매크로 전처리기로 자동 생성 할 수도 있습니다. 그래도 털이 많아 질 것입니다.

그리고 이걸 원하지 않는 이유 # 2, 아마도 이것이 가장 좋은 이유 : 컴파일 속도 입니다. 일반적으로 C 소스 파일은 파일 자체가 변경되거나 여기에 포함 된 파일이 변경 될 때만 재 컴파일하면됩니다.

  • C 파일은 자주 변경 될 수 있지만 변경에는 변경된 파일 하나만 다시 컴파일해야합니다.
  • 헤더 파일은 인터페이스를 정의하므로 자주 변경되지 않아야합니다. 그러나 그렇게하면이 를 포함하는 모든 소스 파일 의 재 컴파일을 트리거 합니다.

모든 파일이 헤더와 소스 파일을 결합하면 모든 변경 사항이 모든 소스 파일의 재 컴파일을 트리거합니다. C ++는 지금도 빠른 컴파일 시간으로 알려져 있지 않습니다. 매번 전체 프로젝트를 다시 컴파일해야 할 때 어떤 일이 발생할지 상상해보십시오. 그런 다음 복잡한 종속성이있는 수백 개의 소스 파일 프로젝트에이를 추정합니다.


미안하지만 C ++에서 헤더를 제거하기위한 "모범 사례"는 없습니다. 그것은 나쁜 생각입니다. 그토록 싫어한다면 세 가지 선택이 있습니다.

  • C ++ 내부 및 사용중인 컴파일러에 대해 잘 알고 있어야합니다. 일반 C ++ 개발자와는 다른 문제에 직면하게되며 많은 도움없이 문제를 해결해야 할 것입니다.
  • 우울하지 않고 "올바르게"사용할 수있는 언어를 선택하십시오.
  • 당신을 위해 그들을 생성하는 도구를 얻으십시오; 여전히 헤더가 있지만 타이핑 노력을 절약 할 수 있습니다.

Pedro Guerreiro는 그의 기사 에서 C ++의 계약에 의한 디자인에 대한 단순 지원에서 다음과 같이 말했습니다.

일반적으로 C ++ 클래스는 헤더 파일과 정의 파일의 두 파일로 제공됩니다. 어설 션은 사양이므로 헤더 파일에서 어설 션을 어디에 써야합니까? 아니면 정의 파일에서 실행 가능하기 때문에? 아니면 둘 다에서 불일치 (및 중복 작업)의 위험이 있습니까? 대신 Java 및 Eiffel처럼 모든 함수가 인라인으로 정의 된 것처럼 기존 스타일을 버리고 헤더 파일 만 사용하여 정의 파일을 제거하는 것이 좋습니다.

이것은 C ++ 정상 성에서 매우 급격한 변화로 처음에 노력을 죽일 위험이 있습니다. 반면에 각 클래스에 대해 두 개의 파일을 유지하는 것은 너무 어색하기 때문에 조만간 C ++ 개발 환경이 생겨서 저장 위치에 대해 걱정할 필요없이 클래스에 집중할 수 있습니다.

2001 년이었습니다. 동의했습니다. 지금은 2009 년이지만 아직까지 "그것을 숨기고 수업에 집중할 수있는 개발 환경"이 나오지 않았습니다. 대신 긴 컴파일 시간이 표준입니다.


참고 : 위의 링크는 현재 작동하지 않는 것 같습니다. 이것은 저자 웹 사이트 출판물 섹션에 나와 있는 출판물에 대한 전체 참조입니다 .

Pedro Guerreiro, Simple Support for Design by Contract in C ++ , TOOLS USA 2001, Proceedings, pages 24-34, IEEE, 2001.


헤더를 돌아 다니는 실용적인 방법은 없습니다. 당신이 할 수있는 유일한 일은 모든 코드를 하나의 큰 C ++ 파일에 넣는 것입니다. 그것은 유지 관리가 불가능한 엉망으로 끝날 것이므로 그렇게하지 마십시오.

현재 C ++ 헤더 파일은 필수적인 악입니다. 나는 그들을 좋아하지 않지만 주위에 방법이 없습니다. 그래도 문제에 대한 개선과 신선한 아이디어를보고 싶습니다.

BTW - 당신이 그것에 익숙해 일단 그렇지 않아 ++ ... 더 이상 나쁜 C (및뿐만 아니라 다른 언어는) 더 억세스 할수 가지가 있습니다.


내가 당신과 같은 어떤 사람들을 본 것은 헤더에 모든 것을 쓰는 입니다 . 이는 메소드 프로필을 한 번만 작성하면되는 원하는 속성을 제공합니다.

개인적으로 선언과 정의를 분리하는 것이 더 좋은 이유가 아주 많다고 생각하지만, 이것이 당신을 괴롭 히면 원하는 것을 할 수있는 방법이 있습니다.


실제로 함수 선언을 두 번 작성해야합니다 (헤더 파일에 한 번, 구현 파일에 한 번). 함수의 정의 (일명 구현)는 구현 파일에 한 번 작성됩니다.

모든 코드를 헤더 파일에 작성할 수 있지만 (실제로는 C ++의 일반 프로그래밍에서 매우 사용되는 방식입니다), 이는 해당 헤더를 포함하는 모든 C / CPP 파일이 해당 헤더 파일에서 구현을 재 컴파일한다는 것을 의미합니다.

C # 또는 Java와 유사한 시스템을 생각하고 있다면 C ++에서는 불가능합니다.


헤더 파일 생성 소프트웨어가 있습니다. 나는 그것을 사용한 적이 없지만 살펴볼 가치가 있습니다. 예를 들어, mkhdr ! C 및 C ++ 파일을 스캔하고 적절한 헤더 파일을 생성합니다.

(그러나 Richard가 지적했듯이 이것은 특정 C ++ 기능을 사용하는 것을 제한하는 것 같습니다. 대신 여기이 스레드에서 Richard의 답변을 참조하십시오 .)


사실 ... 전체 구현을 파일로 작성할 수 있습니다. 템플릿 클래스는 모두 cpp 파일없이 헤더 파일에 정의되어 있습니다.

원하는 확장으로 저장할 수도 있습니다. 그런 다음 #include 문에 파일을 포함합니다.

/* mycode.cpp */
#pragma once
#include <iostreams.h>

class myclass {
public:
  myclass();

  dothing();
};

myclass::myclass() { }
myclass::dothing()
{
  // code
}

그런 다음 다른 파일에서

/* myothercode.cpp */
#pragma once
#include "mycode.cpp"

int main() {
   myclass A;
   A.dothing();
   return 0;
}

몇 가지 빌드 규칙을 설정해야 할 수도 있지만 작동합니다.


아직 Visual Studio 2012에서 Visual-Assist X를 언급 한 사람은 없습니다.

헤더를 관리하는 데 따르는 고통을 덜어주는 데 사용할 수있는 메뉴와 핫키가 많이 있습니다.

  • "선언 생성"은 현재 함수의 함수 선언을 .hpp 파일로 복사합니다.
  • "Refactor..Change signature"를 사용하면 하나의 명령으로 .cpp 및 .h 파일을 동시에 업데이트 할 수 있습니다.
  • Alt-O를 사용하면 .cpp와 .h 파일간에 즉시 전환 할 수 있습니다.

헤더 피할 있습니다 . 완전히. 그러나 나는 그것을 권장하지 않습니다.

매우 구체적인 몇 가지 제한 사항에 직면하게됩니다. 그중 하나는 순환 참조를 가질 수 없다는 것입니다 (부모 클래스가 ChildNode 클래스의 인스턴스에 대한 포인터를 포함하도록 할 수없고, ChildNode 클래스도 Parent 클래스의 인스턴스에 대한 포인터를 포함하도록 할 수 없습니다. 둘 중 하나 여야합니다.)

코드를 정말 이상하게 만드는 다른 제한 사항이 있습니다. 헤더에 충실하십시오. 실제로 그들을 좋아하는 법을 배우게 될 것입니다 (클래스가 할 수있는 일에 대한 멋진 빠른 개요를 제공하기 때문입니다).


rix0rrr의 인기있는 답변에 대한 변형을 제공하려면 :

// foo.cph

#define INCLUDEMODE
#include "foo.cph"
#include "other.cph"
#undef INCLUDEMODE

void foo()
#if !defined(INCLUDEMODE)
{
   printf("Hello World!\n");
}
#else
;
#endif

void bar()
#if !defined(INCLUDEMODE)
{
    foo();
}
#else
;
#endif

I do not recommend this, bit I think this construction demonstrates the removal of content repetition at the cost of rote repetition. I guess it makes copy-pasta easier? That's not really a virtue.

As with all the other tricks of this nature, a modification to the body of a function will still require recompilation of all files including the file containing that function. Very careful automated tools can partially avoid this, but they would still have to parse the source file to check, and be carefully constructed to not rewrite their output if it's no different.

For other readers: I spent a few minutes trying to figure out include guards in this format, but didn't come up with anything good. Comments?


I understand your problems. I would say that the C++ main problem is the compilation/build method that it inherited from the C. The C/C++ header structure has been designed in times when coding involved less definitions and more implementations. Don't throw bottles on me, but that's how it looks like.

Since then the OOP has conquered the world and the world is more about definitions then implementations. As the result, including headers makes pretty painful to work with a language where the fundamental collections such as the ones in the STL made with templates which are notoriously difficult job for the compiler to deal with. All those magic with the precompiled headers doesn't help so much when it comes to TDD, refactoring tools, the general development environment.

Of course C programmers are not suffering from this too much since they don't have compiler-heavy header files and so they are happy with the pretty straightforward, low-level compilation tool chain. With C++ this is a history of suffering: endless forward declarations, precompiled headers, external parsers, custom preprocessors etc.

Many people, however, does not realize that the C++ is the ONLY language that has strong and modern solutions for high- and low-level problems. It's easy to say that you should go for an other language with proper reflection and build system, but it is non-sense that we have to sacrifice the low-level programming solutions with that and we need to complicate things with low-level language mixed with some virtual-machine/JIT based solution.

I have this idea for some time now, that it would be the most cool thing on earth to have a "unit" based c++ tool-chain, similar to that in D. The problem comes up with the cross-platform part: the object files are able to store any information, no problem with that, but since on windows the object file's structure is different that of the ELF, it would be pain in the ass to implement a cross-platform solution to store and process the half-way-compilation units.


After reading all the other answers, I find it missing that there is ongoing work to add support for modules in the C++ standard. It will not make it to C++0x, but the intention is that it will be tackled in a later Technical Review (rather than waiting for a new standard, that will take ages).

The proposal that was being discussed is N2073.

The bad part of it is that you will not get that, not even with the newest c++0x compilers. You will have to wait. In the mean time, you will have to compromise between the uniqueness of definitions in header-only libraries and the cost of compilation.


As far as I know, no. Headers are an inherent part of C++ as a language. Don't forget that forward declaration allows the compiler to merely include a function pointer to a compiled object/function without having to include the whole function (which you can get around by declaring a function inline (if the compiler feels like it).

If you really, really, really hate making headers, write a perl-script to autogenerate them, instead. I'm not sure I'd recommend it though.


It's completely possible to develop without header files. One can include a source file directly:

#include "MyModule.c"

The major issue with this is one of circular dependencies (ie: in C you must declare a function before calling it). This is not an issue if you design your code completely top-down, but it can take some time to wrap ones head around this sort of design pattern if you're not used to it.

If you absolutely must have circular dependencies, one may want to consider creating a file specifically for declarations and including it before everything else. This is a little inconvenient, but still less pollution than having a header for every C file.

I am currently developing using this method for one of my major projects. Here is a breakdown of advantages I've experienced:

  • Much less file pollution in your source tree.
  • Faster build times. (Only one object file is produced by the compiler, main.o)
  • Simpler make files. (Only one object file is produced by the compiler, main.o)
  • No need to "make clean". Every build is "clean".
  • Less boiler plate code. Less code = less potential bugs.

I've discovered that Gish (a game by Cryptic Sea, Edmund McMillen) used a variation on this technique inside its own source code.


You can carefully lay out your functions so that all of the dependent functions are compiled after their dependencies, but as Nils implied, that is not practical.

Catalin (forgive the missing diacritical marks) also suggested a more practical alternative of defining your methods in the header files. This can actually work in most cases.. especially if you have guards in your header files to make sure they are only included once.

I personally think that header files + declaring functions is much more desirable for 'getting your head around' new code, but that is a personal preference I suppose...


You can do without headers. But, why spend effort trying to avoid carefully worked out best practices that have been developed over many years by experts.

When I wrote basic, I quite liked line numbers. But, I wouldn't think of trying to jam them into C++, because that's not the C++ way. The same goes for headers... and I'm sure other answers explain all the reasoning.


For practical purposes no, it's not possible. Technically, yes, you can. But, frankly, it's an abuse of the language, and you should adapt to the language. Or move to something like C#.


It is best practice to use the header files, and after a while it will grow into you. I agree that having only one file is easier, but It also can leed to bad codeing.

some of these things, althoug feel awkward, allow you to get more then meets the eye.

as an example think about pointers, passing parameters by value/by reference... etc.

for me the header files allow-me to keep my projects properly structured


Learn to recognize that header files are a good thing. They separate how codes appears to another user from the implementation of how it actually performs its operations.

When I use someone's code I do now want to have to wade through all of the implementation to see what the methods are on a class. I care about what the code does, not how it does it.


This has been "revived" thanks to a duplicate...

In any case, the concept of a header is a worthy one, i.e. separate out the interface from the implementation detail. The header outlines how you use a class / method, and not how it does it.

The downside is the detail within headers and all the workarounds necessary. These are the main issues as I see them:

  • dependency generation. When a header is modified, any source file that includes this header requires recompilation. The issue is of course working out which source files actually use it. When a "clean" build is performed it is often necessary to cache the information in some kind of dependency tree for later.

  • include guards. Ok, we all know how to write these but in a perfect system it would not be necessary.

  • private details. Within a class, you must put the private details into the header. Yes, the compiler needs to know the "size" of the class, but in a perfect system it would be able to bind this in a later phase. This leads to all kinds of workaround like pImpl and using abstract base classes even when you only have one implementation just because you want to hide a dependency.

The perfect system would work with

  • separate class definition and declaration
  • A clear bind between these two so the compiler would know where a class declaration and its definition are, and would know what the size of a class.
  • You declare using class rather than pre-processor #include. The compiler knows where to find a class. Once you have done "using class" you can use that class name without qualifying it.

I'd be interested to know how D does it.

With regards to whether you can use C++ without headers, I would say no you need them for abstract base classes and standard library. Aside from that you could get by without them, although you probably would not want to.

ReferenceURL : https://stackoverflow.com/questions/1001639/can-i-write-c-code-without-headers-repetitive-function-declarations

반응형