# C++ Code Generation Attributies can be applied to Workflow classes, functions and members to control the result of C++ code generation. ## @cpp:File("YourFile") This attribute applies to**classes**. It creates a new pair of file**YourFile.h**and**YourFile.cpp**to Since internal classes in Workflow get translated to internal classes in C++, if you assign different file name to class A and B when B is defined inside A, it causes an error. This attribute is useful when the class has methods with**@cpp:UserImpl**. ## @cpp:UserImpl This attribute applies to**constructors, destructors and functions**in classes. Bodies of functions with**@cpp:UserImpl**are ignored, they are left blank in the generated file, allowing users to add custom code lines between: - **/* USER_CONTENT_BEGIN(CLASS-NAME) */** - **/* USER_CONTENT_END() */** When a class contains methods with**@cpp:UserImpl**, custom members can also be added to the generated header file for this class between: - **/* USER_CONTENT_BEGIN(custom members of CLASS-NAME) */** - **/* USER_CONTENT_END() */** When a file contains methods with**@cpp:UserImpl**, custom global declarations can also be added to the generated header file for this class between: - **/* USER_CONTENT_BEGIN(custom global declarations) */** - **/* USER_CONTENT_END() */** When the Workflow script is modified and re-generated, new generated code and custom code lines in specific locations will be merged together, so your work doesn't lost. **IMPORTANT**: If there are braces (**{**and**}**) in custom code lines, they must take the whole line, or the code merging will report errors. ## @cpp:Protected and @cpp:Private These attributes apply to**any members**in classes, except non-auto properties. When a class member is annotated by**@cpp:Protected**, this part of the C++ code will be generated with**protected:**. So as**@cpp:Private**. **NOTE**: these attributes don't affect the Workflow compiler, Workflow script treats all members as public members. ## @cpp:Friend(typeof(YourType)) This attribute applies to**classes**. It generates**friend**declaration in C++ code, allowing**YourType**to access protected or private members of the current class. ## Example ### Workflow Script ``` module SampleModule; class DummyClass { func CallPrivateMethod(my: MyClass^): void { my.Method(); } } @cpp:File("MyClass") @cpp:Friend(typeof(DummyClass)) class MyClass { @cpp:UserImpl @cpp:Private func Method(): void { raise "Not Implemented!"; } } ``` ### Generated C++ Files **IMPORTANT**: - The default file name is configurable, here we assume that it is**SampleModule**. - This is not the full content of generated files. By following[Generating C++ Code](.././workflow/running/generating.md)you will see everything. **SampleModule.h** ``` class DummyClass; class MyClass; class DummyClass : public ::vl::Object, public ::vl::reflection::Description { #ifndef VCZH_DEBUG_NO_REFLECTION friend struct ::vl::reflection::description::CustomTypeDescriptorSelector; #endif public: void CallPrivateMethod(::vl::Ptr<::MyClass> my); DummyClass(); }; /*********************************************************************** Global Variables and Functions ***********************************************************************/ namespace vl_workflow_global { class W05Script { public: static W05Script& Instance(); }; } ``` **SampleModule.cpp** ``` #define GLOBAL_SYMBOL ::vl_workflow_global::W05Script:: #define GLOBAL_NAME ::vl_workflow_global::W05Script::Instance(). #define GLOBAL_OBJ &::vl_workflow_global::W05Script::Instance() /*********************************************************************** Global Variables ***********************************************************************/ BEGIN_GLOBAL_STORAGE_CLASS(vl_workflow_global_W05Script) vl_workflow_global::W05Script instance; INITIALIZE_GLOBAL_STORAGE_CLASS FINALIZE_GLOBAL_STORAGE_CLASS END_GLOBAL_STORAGE_CLASS(vl_workflow_global_W05Script) namespace vl_workflow_global { /*********************************************************************** Global Functions ***********************************************************************/ W05Script& W05Script::Instance() { return Getvl_workflow_global_W05Script().instance; } } /*********************************************************************** Class (::DummyClass) ***********************************************************************/ void DummyClass::CallPrivateMethod(::vl::Ptr<::MyClass> my) { ::vl::__vwsn::This(my.Obj())->Method(); } DummyClass::DummyClass() { } #undef GLOBAL_SYMBOL #undef GLOBAL_NAME #undef GLOBAL_OBJ ``` **MyClass.h** ``` class MyClass : public ::vl::Object, public ::vl::reflection::Description { friend class ::DummyClass; #ifndef VCZH_DEBUG_NO_REFLECTION friend struct ::vl::reflection::description::CustomTypeDescriptorSelector; #endif private: void Method(); public: MyClass(); /* USER_CONTENT_BEGIN(custom members of ::MyClass) */ /* USER_CONTENT_END() */ }; ``` **MyClass.cpp** ``` #define GLOBAL_SYMBOL ::vl_workflow_global::W05Script:: #define GLOBAL_NAME ::vl_workflow_global::W05Script::Instance(). #define GLOBAL_OBJ &::vl_workflow_global::W05Script::Instance() /* USER_CONTENT_BEGIN(custom global declarations) */ /* USER_CONTENT_END() */ /*********************************************************************** Class (::MyClass) ***********************************************************************/ void MyClass::Method() {/* USER_CONTENT_BEGIN(::MyClass) */ throw ::vl::Exception(L"You should implement this function."); }/* USER_CONTENT_END() */ MyClass::MyClass() { } #undef GLOBAL_SYMBOL #undef GLOBAL_NAME #undef GLOBAL_OBJ ```