C++ Klassenhilfstool. nützlich, oder gibts das schon?
-
Hi!
Wäre es nicht schön, einfach mit einen Klassenassistenten ne komplette Klasse mit Klicks zu erstellen? Naja, das is ja noch nich so doll, aber nun kommts. :p
Es wird auch automatisch eine Handle-Klasse erstellt!Ungefähr so stell ich mir das vor:
Es gibt so eine Schema-Datei. Das ist C++ mit ein paar Zusatz-"Funktionen".##. das is kommentar ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// /// /// FILENAME: <!CLASSNAME!>.h /// DESCRIPTION:<!DESCRIPTION!> /// VERSION: 0.01 /// /// COPYRIGHT: Copyright (C) <!YEAR!> by <!AUTHOR!>, <!COMPANY!> (R) /// /// /// HISTORY /// /// DATE | AUTHOR | CHANGE /// <!DATE!> <!AUTHOR!> File created /// /// ##UPPER_BEGIN## #ifndef _<!CLASSNAME!>_H_ #define _<!CLASSNAME!>_H_ ##UPPER_END## namespace <!NAMESPACE!> { ##TEMPLATECLASS_BEGIN## template<<!TEMPLATECLASS_LIST!>> ##TEMPLATECLASS_END## class <!CLASSNAME!> ##BASECLASS_BEGIN## : <!BASECLASS_LIST!> ##BASECLASS_END## { public: ##PUBLIC_FUNCTIONS_START## <!RETURNTYPE!> <!FUNCTIONNAME!>(<!PARAMETER_LIST!> ); ##PUBLIC_FUNCTIONS_END## protected: ##PROTECTED_FUNCTIONS_START## <!RETURNTYPE!> <!FUNCTIONNAME!>(<!PARAMETER_LIST!> ); ##PROTECTED_FUNCTIONS_END## ##PROTECTED_VARIABLES_START## <!VARIABLE_TYPE!> <!VARIABLE_NAME!>; ##PROTECTED_VARIABLES_END## private: ##PRIVATE_FUNCTIONS_START## <!RETURNTYPE!> <!FUNCTIONNAME!>(<!PARAMETER_LIST!> ); ##PRIVATE_FUNCTIONS_END## ##PRIVATE_VARIABLES_START## <!VARIABLE_TYPE!> <!VARIABLE_NAME!>; ##PRIVATE_VARIABLES_END## }; // class <!CLASSNAME!> }; // namespace <!NAMESPACE!> #endif --------------------------------------------------------------------------------- CPP SOURCE #include "<!CLASSNAME!>.h" ##PUBLIC_FUNCTIONS_START## ////////////////////////////////////////////////////////////////////////// // // <!FUNCTIONNAME!> // // <!DESCRIPTION!> // // Last change: <!DATE!>, <!AUTHOR!> // <!RETURNTYPE!> <!CLASSNAME!>::<!FUNCTIONNAME!>(<!PARAMETER_LIST!> ) { <!SOURCECODE!> } ##PUBLIC_FUNCTIONS_END## --------------------------------------------------------------------------------- HandleClass Source #include "<!CLASSNAME!>.h" #include "I<!CLASSNAME!>.h" ##PUBLIC_FUNCTIONS_START## ////////////////////////////////////////////////////////////////////////// // // <!FUNCTIONNAME!> // // <!DESCRIPTION!> // // Last change: <!DATE!>, <!AUTHOR!> // <!RETURNTYPE!> I<!CLASSNAME!>::<!FUNCTIONNAME!>(<!PARAMETER_LIST!> ) { return(m_data-><!FUNCTIONNAME!>(<!PARAMETER_NOTYPE!> )); } ##PUBLIC_FUNCTIONS_END##
Mein Programm läuft diese Datei also durch und ersetzt, z.b. <!CLASSNAME!> zu TestClass. Das Prog läuft auch schon teilweise ganz gut (noch keine grafische Oberfläche, sondern nur Konsole ).
Hier ein Beispiel, was der schon kann:
////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// /// /// FILENAME: TestClass.h /// DESCRIPTION:Test Description /// VERSION: 0.01 /// /// COPYRIGHT: Copyright (C) 2002 by Test Author, Test Company (R) /// /// /// HISTORY /// /// DATE | AUTHOR | CHANGE /// 08-11-2002 Test Author File created /// /// #ifndef _TESTCLASS_H_ #define _TESTCLASS_H_ namespace TestNamespace { template<class T, class E> class TestClass : public BaseClass, private BaseClass2 { public: protected: private: }; // class TestClass }; // namespace TestNamespace #endif
wenn keine Templates angegebn wurden, werden auch keine hinzugefügt. Das gleiche ist auch mit den Basisklassen.
Das Tool is noch net fertig, hab ja auch nur 2 bis drei stunden dran gesessen. Und es ist noch nicht in C++ programmiert, sondern im ekligen modernen PowerBASIC. Das wird sich bald aber ändern Ich wollte mich nämlich erst mit der Programmstruktur/logik auseinandersetzen und nicht mit Stringoperatoren
Hoffentlich habt ihr verstanden, was mein kleines Tool macht...
Wie findet ihr es? Oder gibts das schon? Und würdet ihr es benutzen, wenn es halbwegs einfach und schnell zu benutzen ist?Thx
-
naja viele UML Editoren generieren auch den entsperchenden code, nach den vorgaben des entworfenen UML Diagramms!
aber prinzipiell eine gute idee.
-
ok, gut
mir is da noch was gutes eingefallen. das sollte auch sehr einfach zu implementieren sein.
jemand hatte hier im forum mal die idee gehabt, c++ kommentare im xml format zu schreiben (wie bei c# es MS will). und der jemand meinte, dass es noch nicht son tool gibt.beispiel:
/// /// <class> /// <name>TestClass</name> /// <description>lala. dumdim</description> /// </class> /// class TestClass { ... };
also könnte man in meinen tool etwas integrieren, der aus dieser datei eine komplette xml-datei erzeugt. also eine simple dokumentationstool, wie z.b. doxygen. das ist recht einfach zu implementieren, da ich ja nur alles nach dem dritten slash in die xml-datei schreiben muss. also ganz easy...
hälst du das auch für eine gute idee?
-
Hi,
Einen Vorschlag zu deinem Programm:
Man kann eine Basisklasse angeben und dann in deinem Programm von dieser Klasse erben lassen. Dein Programm erstellt diese Klassen dann und erzeugt automatisch funktionsrümpfe für virtuelle und rein-virtuelle Methoden der Basisklasse.
Kannst du sowas in der Richtung implementieren? Habe schonmal damit angefangen aber nach ner halben Stunde wieder aufgehört, weil mir irgendwie die Lust vergangen ist **g**
-
kann ich ja mal irgendwann mal machen, wenn mein programm schon halbwegs funktioniert
fehlen noch ein paar wichtige sachen, wie z.b. eine grafische oberfläche *g
funktionen, variablen, etc. in der konsole angeben is nich sonderlich schön... und das ganze sollte ja noch nach c++ portiert werden...
-
Hi!
Schreibe doch ein AddIn für das Visual Studio. Wäre doch dann eine ganz feine Sache.
Grüße
-
naja, langsam wird das projekt aber etwas zu komplex..
-
Also für den MSVC benutze ich so ein Ding schon.
Ist halt ein wenig schlichter als das, was Du das vorhast, aber mir paßt es bisher recht gut in den Kram.
Aus ner default.h.cfg/******************************************************************************* ** Copyright(c) 2002 Volkard Henkel ** ** http://www.volkard.de ** *******************************************************************************/ //////////////////////////////////////////////////////////////////////////////// // include guard #ifndef CLASS_H__UID #define CLASS_H__UID #ifdef _MSC_VER #pragma once #endif //////////////////////////////////////////////////////////////////////////////// // includes #include <vhlib/NoCopy.h> //////////////////////////////////////////////////////////////////////////////// // class definition class Class:public NoCopy { private:CURSOR public: Class() { } ~Class() { } }; //////////////////////////////////////////////////////////////////////////////// // include guard #endif//CLASS_H__UID
und ner
default.cpp.cfg/******************************************************************************* ** Copyright(c) 2002 Volkard Henkel ** ** http://www.volkard.de ** *******************************************************************************/ //////////////////////////////////////////////////////////////////////////////// // includes #include "pch.h"//for precompiled headers #define CLASS_CPP__UID #include "Class.h"//to implement here //////////////////////////////////////////////////////////////////////////////// // class implementation
bauts mir nach EIngabe des Klassennamens die entsprechenden Klassenname.h und Klassenname.cpp. Staatt default.*.cfg kann auch ein anderere Name sein, was ich benutze für main.h.cfg (ist leer) und main.cpp.cfg
/******************************************************************************* ** Copyright(c) 2002 Volkard Henkel ** ** http://www.volkard.de ** *******************************************************************************/ //////////////////////////////////////////////////////////////////////////////// // includes #include "pch.h"//for precompiled headers #include <iostream> #include <vhlib/Exception.h> #include <vhlib/windows.h> //////////////////////////////////////////////////////////////////////////////// // implemetation using namespace std; void test() { cout<<"start"<<endl; CURSOR cout<<"end"<<endl; } void wait () { cin.clear(); cin.ignore(cin.rdbuf()->in_avail()); cin.get(); } int __cdecl main() { try { test(); } catch(Exception& e) { cout<<e<<endl; } catch(std::exception& e) { cout<<e.what()<<endl; } if(IsDebuggerPresent()) { cout<<endl<<"Press any key to continue"<<endl; wait(); } return 0; }
Da ich meistens mehrere Projekte bearbeite, um eine Anwendung zu erstellen, fragt mich das Tool immer nach Projektname (nur wenn mehr als 1 Projekt offen) und Klassenname.
ie Suche nach den *.cfg-Dateien geschieht vom entsprechenden Projektverzeichnis aufwärts in Richtung root und der erste match wird verwendet. Dadurch kann man fein Defaulteinstellungen im großen Sourceverzeichnis machen, in den Verzeichnissen für die jeweiligen Arbeitgeber andere Copyrighttexte, standard-includes, coding conventions...
Von langen Listen der Members und so halte ich wenig, da ich die dann schneller im ganz normalen Editor eingegeben hab, nachdem der Rumpf der Klasse vom Tool erzeugt wurde. Erben hab ich gar nicht vorgesehen, weil ich ja nicht so oft rumerbe. Das ist aber ne nette Idee. Wenn's mich mal nerst, die pur virtuellen Funktionen... Ups, da gibts inhaltliche Probleme. Will ich das denn?
-
hmmmm. auch wieder ne gute idee in den verschiedenen verzeichnissen eine andere default-datei reinzutun.
aber irgendwie will ich kein vs-addin haben, sondern den den standard-klassending ersezten. also add->add class. da will ich meinen sitzen haben.
jemand ne idee, wie man das hinkriegen könnte? wenn nicht arbeite ich an meine oberfläche weiter... wäre doch nicht sehr schlimm, wenn das ein externes programm wäre, oder wäre das zu unpraktisch?
-
Kenne kein VS-Admin. Und weiß auch nicht, wie ich sauber das normale File/Add so umbiegen könnte, daß es für meine Zwecke nutzbar ist.
Aber mir war ausreichend, das Makro mit nem Button zu verbinden und in die Iconleiste vom VS zu stopfen.'******************************************************************************' '* Copyright(c) 2002 Volkard Henkel *' '* http://www.volkard.de *' '******************************************************************************' option explicit function GetProject if(Application.Projects.Count=0) then MsgBox "No Projekts in Workspace",vbOKOnly+vbInformation set GetProject=nothing exit function end if if(Application.Projects.Count=1) then set GetProject=Application.ActiveProject exit function end if do Dim vProjectName vProjectName=InputBox("Name of Projekt","MakeClass",Application.ActiveProject.Name) if vProjectName="" then set GetProject=nothing exit function end if dim i For Each i in Application.Projects if(i.Name=vProjectName) then set GetProject=i exit function end if next loop 'endlos end function function MakeUid dim i,vResult for i=1 to 8 vResult=vResult+chr(int(asc("0")+rnd*10)) next MakeUid=vResult end function function FindConfigFile(vFso,vProjectFolder,vName,vExt) dim vConfigFolder set vConfigFolder=vProjectFolder if vFso.FileExists(vConfigFolder.Path&"\"&vName&vExt) then MsgBox "File existiert",vbOKOnly+vbInformation set FindConfigFile=nothing exit function end if if vFso.FileExists(vConfigFolder.Path&"\"&"default"&vExt&".cfg") then set FindConfigFile=vFso.GetFile(vConfigFolder.Path&"\"&"default"&vExt&".cfg") exit function end if set vConfigFolder=vConfigFolder.ParentFolder do until vConfigFolder.IsRootFolder if vFso.FileExists(vConfigFolder.Path&"\"&vName&vExt&".cfg") then set FindConfigFile=vFso.GetFile(vConfigFolder.Path&"\"&vName&vExt&".cfg") exit function end if if vFso.FileExists(vConfigFolder.Path&"\"&"default"&vExt&".cfg") then set FindConfigFile=vFso.GetFile(vConfigFolder.Path&"\"&"default"&vExt&".cfg") exit function end if set vConfigFolder=vConfigFolder.ParentFolder loop if vConfigFolder.IsRootFolder then MsgBox "Could not find File",vbOKOnly+vbCritical set FindConfigFile=nothing end if end function Sub ProcessConfigFile(vStream,vClass,vUid) dim vLine do while not vStream.AtEndOfStream vLine=vStream.ReadLine vLine=replace(vLine,"UID",vUid) vLine=replace(vLine,"Class",vClass) vLine=replace(vLine,"CLASS",UCase(vClass)) ActiveDocument.Selection=vLine ActiveDocument.Selection.NewLine ActiveDocument.Selection.StartOfLine loop ActiveDocument.Selection.FindText "CURSOR",dsMatchFromStart ActiveDocument.Selection.Delete end sub Sub MakeFile(vProject,vUid,vClass,vExt) dim vFso,vFile,vProjectFolder,vStream set vFso=CreateObject("Scripting.FileSystemObject") set vProjectFolder=vFso.GetFile(vProject.FullName).ParentFolder set vFile=FindConfigFile(vFso,vProjectFolder,vClass,vExt) if vFile is nothing then exit sub end if Set vStream=vFile.OpenAsTextStream(1,0) if vStream.AtEndOfStream then exit sub end if vProject.AddFile vClass&vExt Documents.Add "Text" ProcessConfigFile vStream,vClass,vUid ActiveDocument.Save vProjectFolder&"\"&vClass&vExt end sub Sub MakeClass() dim vProject set vProject=GetProject() if vProject is nothing then exit sub end if if vProject.Type<>"Build" then MsgBox "No Build Project",vbOKOnly+vbCritical exit sub end if dim vClass vClass=inputbox("Name of Class","MakeClass") if vClass="" then exit sub end if dim vUid vUid=MakeUid MakeFile vProject,vUid,vClass,".cpp" MakeFile vProject,vUid,vClass,".h" End Sub