Forum: PC-Programmierung Visual C++: Wie Header-Dateien codefrei halten?


von Erwin M. (nobodyy)


Lesenswert?

Mit dem Visual C++ (2008) habe ich das Problem, das es in Header-Dateien 
keine einzige Deklarationen packt, sondern nur die Definitionen, 
praktisch den ganzen Code!
Damit ist es beispielsweise nicht möglich auf Methoden der Klassen in 
Form1.h zuzugreifen, weil die Definitionen dazu fehlen und Includieren 
der mißgestalteten Header-Dateien, die eigentlich Quellcode-Dateien 
sind, funktionert auch nicht, u. a. weil das unendliche 
Include-Schleifen zu Folge hätte.
Wie kann man a) der IDE abstellen in Header-Dateien (.h) Code zu packen 
und b) dazu bringen Header-Dateien nur mit den Deklarationen zu 
erstellen?

Als Workaround habe ich begonnen Code (Definitionen) und globale 
Variablen in zum Projekt zugefügte .cpp-Dateien zu Packen und 
Deklarationen in .h-Dateien, aber diese Sysiphos-Arbeit ist doch 
eigentlich Aufgabe der IDE. Kann die wirklich keine richtigen 
Header-Dateien, also solche die nur Deklarationen enthalten, erstellen?

von Peter II (Gast)


Lesenswert?

mach mal bitte ein Beispiel.

Wieso erzeugt die IDE überhaupt code, ich schreibe den code immer selber 
und dann schreibe ich ihn dort rein wo ich ihn haben will?

von Erwin M. (nobodyy)


Lesenswert?

Peter II schrieb:
> mach mal bitte ein Beispiel.

Beispielsweise der Code zu einem Button oder Label und auch der Code zu 
den zugehörigen Events. Den packt die IDE ganz gnadenlos in die 
Header-Datei (.h) zur Form, wobei sie die Deklarationen einfach 
weglässt.
Ich will aber, so wie man das direkt selber programmiert, den Code in 
einer Quellcode-Datei (.cpp) und in der Header-Datei dazu nur die 
Deklarationen, damit ich die Methoden der Klassen woanders einbinden 
kann, beispielsweise um von einem Thread einer anderen Klasse darauf 
zugreifen zu können.
Ich habe schon Tricks wie Pointer auf Funktionen versucht, aber das 
funktioniert beim VC++ nicht. Ich brauche daher richtige Header-Dateien, 
die nur Deklarationen enthalten und da die IDE die Definitionen erstellt 
kann sie das auch, aber ich finde keine Möglichkeit die ausgeben zu 
lassen. Hat Microsoft das abgestellt oder habe ich nur an den falschen 
Stellen gesucht?

von Peter II (Gast)


Lesenswert?

Sicher das du C++ und nicht C++/cli machst?

von Erwin M. (nobodyy)


Lesenswert?

Peter II schrieb:
> Sicher das du C++ und nicht C++/cli machst?

Ja.
Man findet die Unsitte Code in Header-Dateien zu packen und die 
Deklarationen wegzulassen, vom ClassWizard, auch beispielsweise hier:

http://home.wtal.de/ranzurmall/visualc/

Für ein HelloWorld-Programm ist das noch tragbar, für eine ausgewachsene 
Applikation mit etlichen Threads und BackgroundWorkern ist das 
untragbar.

von Peter II (Gast)


Lesenswert?

Erwin Meyer schrieb:
> Applikation mit etlichen Threads und BackgroundWorkern ist das
> untragbar.

so eine anwendung schreibt mach auch nicht mit dem Wizzard sondern 
programmiert per hand.

von Erwin M. (nobodyy)


Lesenswert?

Peter II schrieb:
> Erwin Meyer schrieb:
>> Applikation mit etlichen Threads und BackgroundWorkern ist das
>> untragbar.
>
> so eine anwendung schreibt mach auch nicht mit dem Wizzard sondern
> programmiert per hand.

Also ich will doch nur das der Wizzard auschließlch Deklarationen in die 
Header-Datei schreibt und die Definitionen, die er schon bisher macht, 
in eine .cpp-Datei.
Das ist doch einfach und wird traditionell von Hand gemacht, also muss 
der Wizzard das können. Aber wie bekomme ich den dazu es auch zu machen?

von Peter II (Gast)


Lesenswert?

also bei mir wird es ein die cpp datei eingefügt

[trestetxxDlg.cpp]

void CtrestetxxDlg::OnBnClickedOk()
{
  // TODO: Add your control notification handler code here
  CDialogEx::OnOK();
}

von Erwin M. (nobodyy)


Lesenswert?

Peter II schrieb:
> also bei mir wird es ein die cpp datei eingefügt

Aha, und wie hast Du das hinbekommen?
Und wird eine .h-Datei mit den Deklarationen angelegt?

von Peter II (Gast)


Lesenswert?

Erwin Meyer schrieb:
> Aha, und wie hast Du das hinbekommen?

einfach doppelklick auf einen button

> Und wird eine .h-Datei mit den Deklarationen angelegt?

ja, wie erwartet

[trestetxxDlg.h]
[...]
protected:
  HICON m_hIcon;

  // Generated message map functions
  virtual BOOL OnInitDialog();
  afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
  afx_msg void OnPaint();
  afx_msg HCURSOR OnQueryDragIcon();
  DECLARE_MESSAGE_MAP()
public:
  afx_msg void OnBnClickedOk();
};

von Erwin M. (nobodyy)


Lesenswert?

Peter II schrieb:
> Erwin Meyer schrieb:
>> Aha, und wie hast Du das hinbekommen?
>
> einfach doppelklick auf einen button
> ...

Aha, dann hast Du es so wie es sein sollte also Code/Definitionen nur in 
.cpp-Dateien und Deklarationen nur in .h-Dateien, aber wie hast Du das 
hinbekommen?
Irgendwo muss man das einstellen können, aber wo?

von Rolf (Gast)


Lesenswert?

Erwin Meyer schrieb:
> Irgendwo muss man das einstellen können, aber wo?

Das ist die Defaulteinstellung.

von Erwin M. (nobodyy)


Lesenswert?

Rolf schrieb:
> Erwin Meyer schrieb:
>> Irgendwo muss man das einstellen können, aber wo?
>
> Das ist die Defaulteinstellung.

Nein, beim VC++ 2008 zumindest nicht.

von Karl H. (kbuchegg)


Lesenswert?

Erwin Meyer schrieb:
> Rolf schrieb:
>> Erwin Meyer schrieb:
>>> Irgendwo muss man das einstellen können, aber wo?
>>
>> Das ist die Defaulteinstellung.
>
> Nein, beim VC++ 2008 zumindest nicht.

?

Mir ist absolut nicht klar, wie du das hinbekommen hast.
Ich hab noch in keinem Visual Studio (und ich benutze das seit der 
Version 4 aus dem Jahre 1993) irgendeine Konfigurationsoption in dieser 
Richtung gesehen oder geschweige denn umgestellt.

(Das ich die Entwicklung, die der Wizard genommen hat, nicht leiden 
kann, steht auf einem anderen Blatt. Ich finde, früher war der Dialog 
besser zu bedienen als jetzt dieser Krampf mit dem Property Window und 
Kontext Menü, aber das ist meine Meinung. Aber bisher war das noch immer 
so, dass der Wizzard sauber die Dinge ins Header-File/Source Code-File 
verteilt hat, so wie es sein soll.)

von Erwin M. (nobodyy)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Erwin Meyer schrieb:
>> Rolf schrieb:
>>> Erwin Meyer schrieb:
>>>> Irgendwo muss man das einstellen können, aber wo?
>>>
>>> Das ist die Defaulteinstellung.
>>
>> Nein, beim VC++ 2008 zumindest nicht.
>
> ?
>
> Mir ist absolut nicht klar, wie du das hinbekommen hast.
> Ich hab noch in keinem Visual Studio (und ich benutze das seit der
> Version 4 aus dem Jahre 1993) irgendeine Konfigurationsoption in dieser
> Richtung gesehen oder geschweige denn umgestellt.

Dann hast Du irgendwas anderes.
Ich habe noch nie eine Deklaration vom Wizard gesehen, so als ob der nur 
Definitionen machen kann.
Da aber Deklarationen einfacher sind als Definitionen kann es nur sein 
das Microsoft das abgestellt hat. Irgendwo muss man das doch wieder 
einschalten können.

von Peter II (Gast)


Lesenswert?

Erwin Meyer schrieb:
> Ich habe noch nie eine Deklaration vom Wizard gesehen, so als ob der nur
> Definitionen machen kann.

das geht doch gar nicht. Man kann doch bei ein klasse nicht einfach eine 
Methode schreiben ohne sie in der header datei zu deklarieren.

Ich verwende auch seit VS2003 diese IDE und es hat immer funktioniert.

Ich kann es wirklich immer noch nicht glauben. Erstelle doch bitte mal 
ein einfaches MFC-Dialog Pojekt mit einem Button und dem passenden 
event. Dann zeigst du uns mal den erzeugten code.

von Karl H. (kbuchegg)


Lesenswert?

Erwin Meyer schrieb:
> Karl Heinz Buchegger schrieb:

>> Mir ist absolut nicht klar, wie du das hinbekommen hast.
>> Ich hab noch in keinem Visual Studio (und ich benutze das seit der
>> Version 4 aus dem Jahre 1993) irgendeine Konfigurationsoption in dieser
>> Richtung gesehen oder geschweige denn umgestellt.
>
> Dann hast Du irgendwas anderes.

Ne, ne.
Ich benutze schon VS-Studio.

Aber vielleicht reden wir ja auch von verschiedenen Dingen?

Wie Peter II sagt: Mehr Input!

von Christian R. (supachris)


Lesenswert?

Benutzt er vielleicht diese managed C++ Perversion? Bei MFC mit echtem 
C++ ist das schon immer ordentlich getrennt.

von Erwin M. (nobodyy)


Lesenswert?

Also ich habe mit dem aktuellen VC++ 2010 Express mit 
Default-Einstellungen ein neues Windows-Forms-Projekt erstellt, einen 
Button in die Form gepackt und der Code, der durch Doppelclick darauf 
erzeugt wird, die Definition für button1_Click, wird in Form1.h 
geschrieben. Und auch der gesamte restliche Code zu Form1 ist dort - 
während keine Deklarationen dazu angelegt werden.

Wenn nun von einer anderen Form, die in einem anderen Thread läuft, 
beispielsweise button1_Click verwendet werden soll, muss man erstmal den 
Code aus Form1.h in eine neue Datei, Form1.cpp, packen und in Form1.h 
nur Deklarationen schreiben, die dann z. B. von Form2.cpp inkludiert 
werden können um von Form2 aus auf Form1 zuzugreifen.

von Rolf (Gast)


Lesenswert?

Erwin Meyer schrieb:
> einen
> Button in die Form gepackt und der Code, der durch Doppelclick darauf
> erzeugt wird, die Definition für button1_Click, wird in Form1.h
> geschrieben.

Bei mir wird das in From1.cpp geschrieben.

von Peter II (Gast)


Lesenswert?

Erwin Meyer schrieb:
> Also ich habe mit dem aktuellen VC++ 2010 Express mit
> Default-Einstellungen ein neues Windows-Forms-Projekt erstellt, einen
> Button in die Form gepackt und der Code, der durch Doppelclick darauf
> erzeugt wird, die Definition für button1_Click, wird in Form1.h
> geschrieben. Und auch der gesamte restliche Code zu Form1 ist dort -
> während keine Deklarationen dazu angelegt werden.

lade das Projekt bitte mal hoch, wir wollen es selber sehen!

von Peter II (Gast)


Lesenswert?

Ich habe die Lösung!


Wie schon oben vermute programmiert du ebend nicht C++ sonder CLR. Das 
ist C++ mit .net. Und dort es es so das der code in der *.h Datei 
landet. Dies wird aber auch so gewollt sein.

Etweder schriebst du richtiges C++ oder nimmst C# aber mit CLR wirst du 
nicht glücklich.

von Klaus W. (mfgkw)


Lesenswert?

Wobei bei "richtigem C++" es auch durchaus möglich und ggf. sinnvoll 
ist, Code in der .h zu lassen (direkt in der class...).
Falls das Schwierigkeiten macht, hat man woanders etwas vermurkst.

von Erwin M. (nobodyy)


Lesenswert?

Klaus Wachtler schrieb:
> Wobei bei "richtigem C++" es auch durchaus möglich und ggf. sinnvoll
> ist, Code in der .h zu lassen (direkt in der class...).

Und wie willst Du so die Methoden von Klassen von anderen 
Dateien/Threads aus aufrufen können?

Ohne die Deklarationen geht das bestenfalls mit meist wenig sinnvollen 
Tricks wie Funktionspointern, aber das VC++ liefert mir dazu nur 
Fehlermeldungen.

von Peter II (Gast)


Lesenswert?

Erwin Meyer schrieb:
> Und wie willst Du so die Methoden von Klassen von anderen
> Dateien/Threads aus aufrufen können?

in dem man die header datei einbindet? Wo soll da das Problem sein?

von Karl H. (kbuchegg)


Lesenswert?

Erwin Meyer schrieb:
> Klaus Wachtler schrieb:
>> Wobei bei "richtigem C++" es auch durchaus möglich und ggf. sinnvoll
>> ist, Code in der .h zu lassen (direkt in der class...).
>
> Und wie willst Du so die Methoden von Klassen von anderen
> Dateien/Threads aus aufrufen können?

ja ganz normal.
Header Datei einbinden und einfach aufrufen.
Das ist doch das Bier vom Compiler und Linker wie sie das mit inline 
Funktionen machen.

> Ohne die Deklarationen geht das bestenfalls mit meist wenig sinnvollen
> Tricks wie Funktionspointern, aber das VC++ liefert mir dazu nur
> Fehlermeldungen.

Quatsch.
Da musst du halt mal die Fehlermeldung lesen und darüber sinnieren wie 
und wodurch sie WIRKLICH entsteht.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> ja ganz normal.
> Header Datei einbinden und einfach aufrufen.

Ich vermute mal das die inline Funktionen nicht das Problem sind,

Erwin Meyer schrieb:
> u. a. weil das unendliche
> Include-Schleifen zu Folge hätte

liest sich eher so als ob ein include guard fehlt...

von Karl H. (kbuchegg)


Lesenswert?

Läubi .. schrieb:

> Erwin Meyer schrieb:
>> u. a. weil das unendliche
>> Include-Schleifen zu Folge hätte
>
> liest sich eher so als ob ein include guard fehlt...

Tja.
Wenn man das wüsste.

Peter II hat ja schon eine mögliche Erklärung, was er eigentlich macht. 
Aber es erklärt immer noch nicht, warum das bei ihm nicht kompiliert.

Wenn man mal halt ein File sehen könnte, so wie es bei ihm entsteht.

von Erwin M. (nobodyy)


Lesenswert?

Peter II schrieb:
> Erwin Meyer schrieb:
>> Und wie willst Du so die Methoden von Klassen von anderen
>> Dateien/Threads aus aufrufen können?
>
> in dem man die header datei einbindet? Wo soll da das Problem sein?

Das geht nicht: 1.) würde der Code dadurch repliziert; d. h. die Klassen 
in Form1.h würde nicht nur in der Haupt-Datei (prjekt1.cpp) definiert, 
sondern auch in allen anderen, die die Form1.h ebenfalls inkludieren und 
2.) werden für den Code des Main-Thread, also defaultmässig in Form1.h, 
Definitionen anderer Klassen inkludiert, was zu Endlosschleifen führt, 
die mangels expliziter Deklarationen nicht durch Vorwärts-Deklarationen 
gelöst werden kann.

von Peter II (Gast)


Lesenswert?

Erwin Meyer schrieb:
> Das geht nicht: 1.) würde der Code dadurch repliziert; d. h. die Klassen
> in Form1.h würde nicht nur in der Haupt-Datei (prjekt1.cpp) definiert,
> sondern auch in allen anderen, die die Form1.h ebenfalls inkludieren und
> 2.) werden für den Code des Main-Thread, also defaultmässig in Form1.h,
> Definitionen anderer Klassen inkludiert, was zu Endlosschleifen führt,
> die mangels expliziter Deklarationen nicht durch Vorwärts-Deklarationen
> gelöst werden kann.

dafür gibt es ein include guard.

Du solltest vielleicht mal leute glauben, wie wenigsten wissen in 
welcher Sprache sie programmieren.


Außerdem sollte man immer vom Main-Thread auf die GUI(Form) zugreifen 
und niemals aus worker Threads.

von Klaus W. (mfgkw)


Lesenswert?

Erwin Meyer schrieb:
> Das geht nicht: 1.) würde der Code dadurch repliziert; d. h. die Klassen
> in Form1.h würde nicht nur in der Haupt-Datei (prjekt1.cpp) definiert,
> sondern auch in allen anderen, die die Form1.h ebenfalls inkludieren und

Das ist falsch.
Richtig ist, daß der Compiler entweder den Inhalt der Methoden inline 
einfügt, dann wird Code repliziert, dann ist das aber auch gewollt - 
weil der Rumpf klein ist gegenüber dem Aufwand eines Funktionsaufrufs, 
oder (wenn der Rumpf nach Ansicht des Compilers zu groß ist) wird in 
jedem so kompilierten Quelltext eine Funktion erzeugt (weil der Compiler 
ja nichts von den anderen weiß), aber der Linker nimmt dann letztlich 
nur eine davon, wirft die anderen weg und im fertigen Programm ist alles 
in Ordnung.

> 2.) ...

siehe oben Peter II

von Rolf (Gast)


Lesenswert?

@ Erwin Meyer:

Schau mal hier:

http://blog.kalmbach-software.de/de/2010/03/05/ccli-und-winforms-macht-keinen-sinn/

Da wird dein beobachtetes Verhalten bestätigt:
"Der WinForms-Designer ist miserabel, da er die Implementierung von 
Methoden in der h-Datei vornimmt, was spätestens zu Problemen führt, 
wenn man mehr als ein Form hat und auf Methoden/Properties des anderen 
Forms zugreifen will (da man dann zyklische Abhängigkeiten in den 
h-Dateien hat, die man nur lösen kann, wenn man die Implementierung in 
die cpp-Datei verlegt)"

von Erwin M. (nobodyy)


Lesenswert?

Rolf schrieb:
> @ Erwin Meyer:
>
> Schau mal hier:
>
> 
http://blog.kalmbach-software.de/de/2010/03/05/ccli-und-winforms-macht-keinen-sinn/
>
> Da wird dein beobachtetes Verhalten bestätigt:
> "Der WinForms-Designer ist miserabel, da er die Implementierung von
> Methoden in der h-Datei vornimmt, was spätestens zu Problemen führt,
> wenn man mehr als ein Form hat und auf Methoden/Properties des anderen
> Forms zugreifen will (da man dann zyklische Abhängigkeiten in den
> h-Dateien hat, die man nur lösen kann, wenn man die Implementierung in
> die cpp-Datei verlegt)"

Ja, also gibt es keine richtige Lösung; nur von Hand verschieben und 
Deklarationen selber machen hilft hier.

von Karl H. (kbuchegg)


Lesenswert?

Erwin Meyer schrieb:

> Ja, also gibt es keine richtige Lösung;

Doch die gibt es.

Programmier entweder in richtigem C++ oder nimm C#, wenn du auf das 
WinForms Zeugs stehst.
Aber lass die Finger von diesem bescheuerten C++/CLI!

C++/CLI ist ein Eigentor von Microsoft. Nicht Fisch - nicht Fleisch. 
Dieser Bastard hat sowieso keine längerfristige Zukunft. Da kannst du 
auch gleich auf C# setzen. Solche Leute werden wenigstens von der 
Industrie gesucht. Aber mit C++/CLI reißt du da draussen nichts. Gar 
nichts.

von Forest D. (thecomet)


Lesenswert?

Du solltest in deine Header auch mit Header Guards ausstatten:

"vector3.hpp"
1
#ifndef _VECTOR3_H_
2
   #define _VECTOR3_H_
3
4
class vec3
5
{
6
   public:
7
8
      // vector components
9
      float x;
10
      float y;
11
      float z;
12
13
      // constructor, destructor
14
      vec3( void );
15
      vec3( float x, float y, float z );
16
      virtual ~vec3( void );
17
18
};
19
20
#endif // _VECTOR3_H_

"vector3.cpp"
1
// include files
2
#include "vector3.hpp"
3
4
// --------------------------------------------------------------
5
// constructor with arguments
6
vec3::vec3( float x, float y, float z )
7
{
8
   this->x = x;
9
   this->y = y;
10
   this->z = z;
11
   return;
12
}
13
14
// --------------------------------------------------------------
15
// constructor with no arguments
16
vec3::vec3( void )
17
{
18
}
19
20
// --------------------------------------------------------------
21
// destructor
22
vec3::~vec3( void )
23
{
24
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.