Full Code of Light-City/CPlusPlusThings for AI

master 7e98e7ccbf7c cached
675 files
745.6 KB
287.0k tokens
1846 symbols
1 requests
Download .txt
Showing preview only (883K chars total). Download the full file or copy to clipboard to get everything.
Repository: Light-City/CPlusPlusThings
Branch: master
Commit: 7e98e7ccbf7c
Files: 675
Total size: 745.6 KB

Directory structure:
gitextract_54wk3wyp/

├── .gitignore
├── README.md
├── README_EN.md
├── WORKSPACE
├── basic_content/
│   ├── abstract/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── abstract.cpp
│   │   ├── abstract_base.h
│   │   ├── derived_full.cpp
│   │   ├── interesting_facts1.cpp
│   │   ├── interesting_facts2.cpp
│   │   ├── interesting_facts3.cpp
│   │   ├── interesting_facts4.cpp
│   │   ├── interesting_facts5.cpp
│   │   └── pure_virtual.cpp
│   ├── assert/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── assert.c
│   │   └── ignore_assert.c
│   ├── bit/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── bit.cpp
│   ├── c_poly/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── c++_examp.cpp
│   │   └── c_examp.c
│   ├── const/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── class_const/
│   │   │   ├── c++11_example/
│   │   │   │   ├── BUILD
│   │   │   │   ├── apple.cpp
│   │   │   │   ├── apple.h
│   │   │   │   └── main.cpp
│   │   │   ├── first_example/
│   │   │   │   ├── BUILD
│   │   │   │   ├── apple.cpp
│   │   │   │   ├── apple.h
│   │   │   │   └── main.cpp
│   │   │   ├── overload_example/
│   │   │   │   ├── BUILD
│   │   │   │   ├── apple.cpp
│   │   │   │   ├── apple.h
│   │   │   │   └── main.cpp
│   │   │   └── static_example/
│   │   │       ├── BUILD
│   │   │       ├── apple.cpp
│   │   │       ├── apple.h
│   │   │       └── main.cpp
│   │   ├── const_function.cpp
│   │   ├── const_num.cpp
│   │   ├── extern_const/
│   │   │   ├── BUILD
│   │   │   ├── const_file1.cpp
│   │   │   ├── const_file2.cpp
│   │   │   ├── file1.cpp
│   │   │   └── file2.cpp
│   │   └── funciton_const/
│   │       ├── condition1/
│   │       │   ├── BUILD
│   │       │   ├── condition1.cpp
│   │       │   ├── condition2.cpp
│   │       │   └── condition3.cpp
│   │       ├── condition2/
│   │       │   ├── BUILD
│   │       │   ├── condition1.cpp
│   │       │   ├── condition2.cpp
│   │       │   └── condition3.cpp
│   │       └── condition3/
│   │           ├── BUILD
│   │           └── condition1.cpp
│   ├── decltype/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── decltype.cpp
│   ├── enum/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── classic_practice.cpp
│   │   └── tradition_color.cpp
│   ├── explicit/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── explicit.cpp
│   ├── extern/
│   │   ├── README.md
│   │   ├── extern_c/
│   │   │   ├── BUILD
│   │   │   ├── add.c
│   │   │   ├── add.cpp
│   │   │   └── add.h
│   │   └── extern_c++/
│   │       ├── BUILD
│   │       ├── add.c
│   │       ├── add.cpp
│   │       └── add.h
│   ├── friend/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── friend_class.cpp
│   │   └── friend_func.cpp
│   ├── func_pointer/
│   │   ├── BUILD
│   │   └── func_pointer.cpp
│   ├── inline/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── inline.cpp
│   │   ├── inline.h
│   │   └── inline_virtual.cpp
│   ├── macro/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── do_while.cpp
│   │   └── sig_examp.cpp
│   ├── maohao/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── maohao.cpp
│   ├── pointer_refer/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── copy_construct.cpp
│   │   └── effec.cpp
│   ├── sizeof/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── blackclass.cpp
│   │   ├── genA.cpp
│   │   ├── geninhe.cpp
│   │   ├── moreinhe.cpp
│   │   ├── morevir.cpp
│   │   ├── static.cpp
│   │   ├── virinhe.cpp
│   │   └── virmoreinhe.cpp
│   ├── static/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── nostatic_class.cpp
│   │   ├── static_class.cpp
│   │   ├── static_demo.cpp
│   │   ├── static_error_variable.cpp
│   │   ├── static_funciton.cpp
│   │   └── static_variable.cpp
│   ├── struct/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── ext_struct_func.cpp
│   │   ├── struct_func.c
│   │   ├── struct_func.cpp
│   │   ├── struct_func_func.cpp
│   │   └── stu
│   ├── struct_class/
│   │   └── README.md
│   ├── this/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── person.cpp
│   ├── union/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── union.cpp
│   ├── using/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── derived_base.cpp
│   │   ├── using_derived.cpp
│   │   ├── using_global.cpp
│   │   └── using_typedef.cpp
│   ├── virtual/
│   │   ├── README.md
│   │   ├── set1/
│   │   │   ├── BUILD
│   │   │   └── emp.cpp
│   │   ├── set2/
│   │   │   ├── BUILD
│   │   │   └── default_arg.cpp
│   │   ├── set3/
│   │   │   ├── BUILD
│   │   │   ├── copy_consrtuct.cpp
│   │   │   ├── full_virde.cpp
│   │   │   ├── inline_virtual.cpp
│   │   │   ├── static_error.cpp
│   │   │   ├── vir_con.cpp
│   │   │   ├── vir_de.cpp
│   │   │   ├── virtual_function.cpp
│   │   │   ├── virtual_function1.cpp
│   │   │   └── virtual_inline.cpp
│   │   └── set4/
│   │       ├── BUILD
│   │       ├── rtti.cpp
│   │       └── warn_rtti.cpp
│   ├── volatile/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── noopt_vola.cpp
│   │   └── volatile.cpp
│   └── vptr_vtable/
│       ├── BUILD
│       ├── README.md
│       └── vptr1.cpp
├── codingStyleIdioms/
│   ├── 1_classInitializers/
│   │   ├── 1.1_nest.cpp
│   │   ├── 1.2_nodefault_ctor.cpp
│   │   ├── 1.3_const.cpp
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── initializer.cpp
│   ├── 2_enumclass/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── namespace.cpp
│   ├── 3_RAII/
│   │   ├── BUILD
│   │   ├── RAII.cpp
│   │   ├── RAII.md
│   │   ├── RAII_fstram.cpp
│   │   ├── c++_example.cpp
│   │   ├── c++_example1.cpp
│   │   ├── c++_example2.cpp
│   │   └── c_example.cpp
│   ├── 4_copy-swap/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── copy-swapAndADL.cpp
│   ├── 5_pImpl/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── noPimpl.cpp
│   │   ├── pimpl.cpp
│   │   ├── pimplTime.cpp
│   │   └── pimplTime.h
│   └── README.md
├── concurrency/
│   ├── Threading_In_CPlusPlus/
│   │   ├── 1.thread/
│   │   │   ├── BUILD
│   │   │   ├── intro.cpp
│   │   │   └── thread.cpp
│   │   ├── 2.create_type/
│   │   │   ├── 1.function_pointer.cpp
│   │   │   ├── 2.lambda_function.cpp
│   │   │   ├── 3.functor.cpp
│   │   │   ├── 4.no_static_member_function.cpp
│   │   │   ├── 5.static_member_function.cpp
│   │   │   └── BUILD
│   │   ├── 3.join_detach/
│   │   │   ├── BUILD
│   │   │   ├── detach.cpp
│   │   │   └── join.cpp
│   │   └── 4.mutex/
│   │       ├── BUILD
│   │       ├── an_example_of_bank_account.cpp
│   │       └── critical_section.cpp
│   └── concurrency_v1/
│       ├── chapter1/
│       │   ├── 1_helloworld.cpp
│       │   └── BUILD
│       └── chapter2/
│           ├── 2.1_basic.cpp
│           ├── 2.2_transfer.cpp
│           ├── 2.3_ownership.cpp
│           ├── 2.4_runtime.cpp
│           ├── 2_5_id.cpp
│           └── BUILD
├── cpp2.0/
│   └── cpp11/
│       ├── BUILD
│       ├── README.md
│       ├── alias.cpp
│       ├── auto.cpp
│       ├── constexpr.cpp
│       ├── decltype.cpp
│       ├── default_delete.cpp
│       ├── explicit.cpp
│       ├── final.cpp
│       ├── hash.cpp
│       ├── initializer.cpp
│       ├── lambda.cpp
│       ├── move.cpp
│       ├── noexcept.cpp
│       ├── nullptr.cpp
│       ├── override.cpp
│       ├── rvalue.cpp
│       ├── template_template.cpp
│       ├── tuple.cpp
│       ├── type_alias.cpp
│       ├── uniform_initialization.cpp
│       └── variadic/
│           ├── BUILD
│           ├── variadic.cpp
│           ├── variadic1.cpp
│           ├── variadic2.cpp
│           ├── variadic3_4.cpp
│           ├── variadic5.cpp
│           ├── variadic6.cpp
│           └── variadic7.cpp
├── design_pattern/
│   ├── producer_consumer/
│   │   ├── BUILD
│   │   └── producer_consumer.cpp
│   └── singleton/
│       ├── README.md
│       ├── barrier_singleton.cpp
│       ├── cpulpuls11_singleton.cpp
│       ├── dcl_singleton.cpp
│       ├── hungrysingleton.cpp
│       ├── iazysingleton.cpp
│       ├── lock_singleton.cpp
│       ├── pthreadoncesingleton.cpp
│       └── static_local_singleton.cpp
├── effective_cpp/
│   ├── 2.cpp
│   └── BUILD
├── english/
│   └── basic_content/
│       ├── abstract/
│       │   ├── README.md
│       │   ├── abstract.cpp
│       │   ├── derived_full.cpp
│       │   ├── interesting_facts1.cpp
│       │   ├── interesting_facts2.cpp
│       │   ├── interesting_facts3.cpp
│       │   ├── interesting_facts4.cpp
│       │   ├── interesting_facts5.cpp
│       │   ├── pure_virtual.cpp
│       │   └── test.cpp
│       ├── assert/
│       │   ├── README.md
│       │   ├── assert.c
│       │   └── ignore_assert.c
│       ├── bit/
│       │   ├── README.md
│       │   └── learn.cpp
│       ├── c_poly/
│       │   ├── README.md
│       │   ├── c++_examp
│       │   ├── c++_examp.cpp
│       │   ├── c_examp
│       │   └── c_examp.c
│       ├── const/
│       │   ├── README.md
│       │   ├── class_const/
│       │   │   ├── c++11_example/
│       │   │   │   ├── apple.cpp
│       │   │   │   ├── main
│       │   │   │   └── main.cpp
│       │   │   ├── first_example/
│       │   │   │   ├── apple.cpp
│       │   │   │   └── main.cpp
│       │   │   ├── overload_example/
│       │   │   │   ├── apple.cpp
│       │   │   │   ├── main
│       │   │   │   └── main.cpp
│       │   │   └── static_example/
│       │   │       ├── apple.cpp
│       │   │       ├── main
│       │   │       └── main.cpp
│       │   ├── const_function.cpp
│       │   ├── const_num.cpp
│       │   ├── extern_const/
│       │   │   ├── const_file1.cpp
│       │   │   ├── const_file2.cpp
│       │   │   ├── file1.cpp
│       │   │   └── file2.cpp
│       │   └── funciton_const/
│       │       ├── condition1/
│       │       │   ├── condition1.cpp
│       │       │   ├── condition2.cpp
│       │       │   └── condition3.cpp
│       │       ├── condition2/
│       │       │   ├── condition1
│       │       │   ├── condition1.cpp
│       │       │   ├── condition2.cpp
│       │       │   ├── condition3
│       │       │   └── condition3.cpp
│       │       └── condition3/
│       │           ├── condition1
│       │           └── condition1.cpp
│       ├── decltype/
│       │   ├── README.md
│       │   ├── decltype
│       │   └── decltype.cpp
│       ├── enum/
│       │   ├── README.md
│       │   ├── classic_practice
│       │   ├── classic_practice.cpp
│       │   └── tradition_color.cpp
│       ├── explicit/
│       │   ├── README.md
│       │   └── explicit.cpp
│       ├── extern/
│       │   ├── README.md
│       │   ├── extern_c/
│       │   │   ├── add.c
│       │   │   ├── add.cpp
│       │   │   ├── add.h
│       │   │   ├── add.o
│       │   │   └── main
│       │   └── extern_c++/
│       │       ├── add.c
│       │       ├── add.cpp
│       │       ├── add.h
│       │       ├── add.o
│       │       └── main
│       ├── friend/
│       │   ├── README.md
│       │   ├── friend_class
│       │   ├── friend_class.cpp
│       │   ├── friend_func
│       │   └── friend_func.cpp
│       ├── func_pointer/
│       │   ├── func1
│       │   └── func_pointer.cpp
│       ├── inline/
│       │   ├── README.md
│       │   ├── inline
│       │   ├── inline.cpp
│       │   ├── inline.h
│       │   ├── inline_virtual.cpp
│       │   └── iv
│       ├── macro/
│       │   ├── README.md
│       │   ├── do_while
│       │   ├── do_while.cpp
│       │   ├── sig_examp
│       │   └── sig_examp.cpp
│       ├── maohao/
│       │   ├── .README.md.un~
│       │   ├── README.md
│       │   ├── README.md~
│       │   └── maohao.cpp
│       ├── pointer_refer/
│       │   ├── README.md
│       │   ├── copy_construct
│       │   ├── copy_construct.cpp
│       │   ├── effec
│       │   └── effec.cpp
│       ├── sizeof/
│       │   ├── README.md
│       │   ├── blackclass.cpp
│       │   ├── genA.cpp
│       │   ├── geninhe.cpp
│       │   ├── moreinhe.cpp
│       │   ├── morevir.cpp
│       │   ├── static.cpp
│       │   ├── virinhe.cpp
│       │   └── virmoreinhe.cpp
│       ├── static/
│       │   ├── README.md
│       │   ├── demo
│       │   ├── nostatic_class.cpp
│       │   ├── static_class.cpp
│       │   ├── static_demo.cpp
│       │   ├── static_error_variable.cpp
│       │   ├── static_funciton.cpp
│       │   └── static_variable.cpp
│       ├── struct/
│       │   ├── README.md
│       │   ├── ext
│       │   ├── ext_struct_func.cpp
│       │   ├── sf
│       │   ├── stff
│       │   ├── struct_func
│       │   ├── struct_func.c
│       │   ├── struct_func.cpp
│       │   ├── struct_func_func.cpp
│       │   └── stu
│       ├── struct_class/
│       │   └── README.md
│       ├── this/
│       │   ├── README.md
│       │   ├── person
│       │   └── person.cpp
│       ├── union/
│       │   ├── README.md
│       │   ├── union
│       │   └── union.cpp
│       ├── using/
│       │   ├── README.md
│       │   ├── derived_base
│       │   ├── derived_base.cpp
│       │   ├── using_derived
│       │   ├── using_derived.cpp
│       │   ├── using_global
│       │   ├── using_global.cpp
│       │   ├── using_typedef
│       │   └── using_typedef.cpp
│       ├── virtual/
│       │   ├── README.md
│       │   ├── set1/
│       │   │   ├── emp
│       │   │   └── emp.cpp
│       │   ├── set2/
│       │   │   └── default_arg.cpp
│       │   ├── set3/
│       │   │   ├── copy_consrtuct.cpp
│       │   │   ├── full_virde.cpp
│       │   │   ├── inline_virtual.cpp
│       │   │   ├── static_error.cpp
│       │   │   ├── vir_con.cpp
│       │   │   ├── vir_de.cpp
│       │   │   ├── virtual_function.cpp
│       │   │   ├── virtual_function1.cpp
│       │   │   └── virtual_inline.cpp
│       │   └── set4/
│       │       ├── rtti
│       │       ├── rtti.cpp
│       │       └── warn_rtti.cpp
│       ├── volatile/
│       │   ├── README.md
│       │   ├── noopt_vola.cpp
│       │   ├── nv
│       │   └── volatile.cpp
│       └── vptr_vtable/
│           ├── README.md
│           └── vptr1.cpp
├── extension/
│   └── some_problem/
│       └── string_int.md
├── learn_class/
│   └── modern_cpp_30/
│       ├── RAII/
│       │   ├── BUILD
│       │   ├── RAII.cpp
│       │   ├── heap.cpp
│       │   └── stack.cpp
│       ├── SFINAE/
│       │   ├── README.md
│       │   ├── SFINAE.cpp
│       │   └── sfinae paper/
│       │       ├── auto.cpp
│       │       ├── blending1.cpp
│       │       ├── blending2.cpp
│       │       ├── combiningAndGenius.cpp
│       │       ├── constexpr.cpp
│       │       ├── decltype.cpp
│       │       ├── fis_valid.cpp
│       │       ├── hana.cpp
│       │       ├── is_valid.cpp
│       │       ├── lambda.cpp
│       │       ├── overload1.cpp
│       │       ├── overload2.cpp
│       │       ├── p1SFINAE.cpp
│       │       ├── p2SFINAE.cpp
│       │       ├── packis_valid.cpp
│       │       ├── serialize.cpp
│       │       ├── sizeof1.cpp
│       │       ├── sizeof2.cpp
│       │       ├── structData.h
│       │       └── timeGenius.cpp
│       ├── compilercompute/
│       │   ├── BUILD
│       │   ├── IF.cpp
│       │   ├── WhileLoop.cpp
│       │   ├── factorial.cpp
│       │   └── fmap.cpp
│       ├── compilerpoly/
│       │   ├── BUILD
│       │   ├── README.md
│       │   └── template.cpp
│       ├── constexpr/
│       │   ├── BUILD
│       │   ├── container.cpp
│       │   ├── newconstexpr.cpp
│       │   ├── output_container.h
│       │   ├── sqrt.cpp
│       │   └── test3.cpp
│       ├── container1/
│       │   ├── BUILD
│       │   ├── container.cpp
│       │   ├── output_container.h
│       │   └── vector_l.cpp
│       ├── container2/
│       │   ├── BUILD
│       │   ├── array.cpp
│       │   ├── hash.cpp
│       │   ├── priority_queue.cpp
│       │   ├── relacontainer.cpp
│       │   └── unorder.cpp
│       ├── exception/
│       │   ├── BUILD
│       │   └── exception.cpp
│       ├── functionLambda/
│       │   ├── BUILD
│       │   ├── adder.cpp
│       │   ├── autoLambda.cpp
│       │   └── function.cpp
│       ├── literalAssert/
│       │   ├── BUILD
│       │   ├── assert.cpp
│       │   ├── default_delete.cpp
│       │   ├── literal.cpp
│       │   └── overridefinal.cpp
│       ├── memorymodel_atomic/
│       │   ├── barrier_singleton.cpp
│       │   ├── cpulpuls11_singleton.cpp
│       │   ├── dcl_singleton.cpp
│       │   ├── hungrysingleton.cpp
│       │   ├── iazysingleton.cpp
│       │   ├── lock_singleton.cpp
│       │   ├── pthreadoncesingleton.cpp
│       │   └── static_local_singleton.cpp
│       ├── obj/
│       │   ├── BUILD
│       │   ├── all.cpp
│       │   ├── obj1.cpp
│       │   ├── obj2.cpp
│       │   ├── obj3.cpp
│       │   ├── obj4.cpp
│       │   └── obj5.cpp
│       ├── reference/
│       │   ├── BUILD
│       │   ├── collapses.cpp
│       │   ├── forward.cpp
│       │   ├── lifetime.cpp
│       │   ├── ref.cpp
│       │   ├── reference.cpp
│       │   └── shape.h
│       └── smart_ptr/
│           ├── README.md
│           ├── auto_scope.cpp
│           ├── shared_ptr.cpp
│           ├── unique_ptr.cpp
│           └── unique_ptr_U.cpp
├── practical_exercises/
│   ├── 10_day_practice/
│   │   ├── day1/
│   │   │   ├── BUILD
│   │   │   ├── annotate.cpp
│   │   │   ├── print.cpp
│   │   │   ├── runnian.cpp
│   │   │   └── union.cpp
│   │   ├── day10/
│   │   │   ├── file/
│   │   │   │   ├── 10-4.cpp
│   │   │   │   ├── 12-1.cpp
│   │   │   │   ├── 12-2.cpp
│   │   │   │   ├── 12-3.cpp
│   │   │   │   ├── 12-5.cpp
│   │   │   │   ├── 12-6.cpp
│   │   │   │   ├── 12-7.cpp
│   │   │   │   ├── 12-9.cpp
│   │   │   │   ├── BUILD
│   │   │   │   ├── input/
│   │   │   │   │   ├── BUILD
│   │   │   │   │   ├── get.cpp
│   │   │   │   │   ├── get2.cpp
│   │   │   │   │   └── getline.cpp
│   │   │   │   └── practice.cpp
│   │   │   └── readme.md
│   │   ├── day2/
│   │   │   ├── BUILD
│   │   │   ├── compute.cpp
│   │   │   ├── enum.cpp
│   │   │   ├── hanoi.cpp
│   │   │   ├── pow.cpp
│   │   │   ├── rec1.cpp
│   │   │   ├── rec2.cpp
│   │   │   ├── shaizi.cpp
│   │   │   ├── st.cpp
│   │   │   └── static.cpp
│   │   ├── day3/
│   │   │   ├── BUILD
│   │   │   ├── inline.cpp
│   │   │   ├── pratice.cpp
│   │   │   ├── predeclare.cpp
│   │   │   ├── static_data.cpp
│   │   │   ├── static_member1.cpp
│   │   │   ├── static_member2.cpp
│   │   │   └── swap.cpp
│   │   ├── day4/
│   │   │   ├── clock/
│   │   │   │   ├── BUILD
│   │   │   │   ├── operator.cpp
│   │   │   │   └── operator_plus.cpp
│   │   │   ├── const/
│   │   │   │   ├── BUILD
│   │   │   │   ├── obj_func.cpp
│   │   │   │   ├── obj_ref.cpp
│   │   │   │   └── readme.md
│   │   │   ├── copy_ctor/
│   │   │   │   ├── BUILD
│   │   │   │   ├── clock.cpp
│   │   │   │   └── clock.h
│   │   │   └── friend/
│   │   │       ├── BUILD
│   │   │       ├── class.cpp
│   │   │       ├── func.cpp
│   │   │       └── readme.md
│   │   ├── day5/
│   │   │   ├── ctor_dtor/
│   │   │   │   ├── BUILD
│   │   │   │   ├── cseq.cpp
│   │   │   │   ├── ctor.cpp
│   │   │   │   ├── ctor_d.cpp
│   │   │   │   ├── noctor.cpp
│   │   │   │   ├── param.cpp
│   │   │   │   ├── readme.md
│   │   │   │   └── seq.cpp
│   │   │   ├── inherit_access/
│   │   │   │   ├── BUILD
│   │   │   │   ├── private.cpp
│   │   │   │   ├── protected.cpp
│   │   │   │   ├── protected_inherit.cpp
│   │   │   │   ├── public.cpp
│   │   │   │   └── readme.md
│   │   │   ├── rela/
│   │   │   │   ├── BUILD
│   │   │   │   ├── readme.md
│   │   │   │   └── rela.cpp
│   │   │   ├── rule/
│   │   │   │   ├── BUILD
│   │   │   │   ├── direct.cpp
│   │   │   │   └── readme.md
│   │   │   └── virtual/
│   │   │       ├── BUILD
│   │   │       ├── example1.cpp
│   │   │       ├── example2.cpp
│   │   │       ├── init.cpp
│   │   │       ├── readme.md
│   │   │       └── seq.cpp
│   │   ├── day6/
│   │   │   ├── abstract_class/
│   │   │   │   ├── BUILD
│   │   │   │   └── main.cpp
│   │   │   ├── readme.md
│   │   │   └── virtual_func/
│   │   │       ├── BUILD
│   │   │       ├── example.cpp
│   │   │       ├── virtual.cpp
│   │   │       ├── virtual_dtor.cpp
│   │   │       ├── virtual_feature.cpp
│   │   │       └── vis.cpp
│   │   ├── day7/
│   │   │   ├── binary_operator/
│   │   │   │   ├── BUILD
│   │   │   │   ├── friend_operator.cpp
│   │   │   │   └── operator.cpp
│   │   │   ├── brackets/
│   │   │   │   ├── BUILD
│   │   │   │   └── brac.cpp
│   │   │   ├── equal_operator/
│   │   │   │   ├── BUILD
│   │   │   │   └── equal_operator.cpp
│   │   │   ├── example/
│   │   │   │   ├── BUILD
│   │   │   │   └── example.cpp
│   │   │   ├── index_parentheses/
│   │   │   │   ├── BUILD
│   │   │   │   └── example.cpp
│   │   │   ├── readme.md
│   │   │   ├── subscript_operator/
│   │   │   │   ├── BUILD
│   │   │   │   └── subscript_operator.cpp
│   │   │   └── unary_operator/
│   │   │       ├── BUILD
│   │   │       ├── time_counter.cpp
│   │   │       └── time_increase.cpp
│   │   ├── day8/
│   │   │   ├── class_template/
│   │   │   │   ├── BUILD
│   │   │   │   ├── spec.cpp
│   │   │   │   └── stack.cpp
│   │   │   ├── func/
│   │   │   │   ├── BUILD
│   │   │   │   ├── main.cpp
│   │   │   │   ├── max.cpp
│   │   │   │   ├── max_spec.cpp
│   │   │   │   └── sort.cpp
│   │   │   ├── readme.md
│   │   │   └── stl/
│   │   │       ├── BUILD
│   │   │       └── map.cpp
│   │   ├── day9/
│   │   │   ├── exception/
│   │   │   │   ├── 1.cpp
│   │   │   │   ├── 10.cpp
│   │   │   │   ├── 2.cpp
│   │   │   │   ├── 3.cpp
│   │   │   │   ├── 4.cpp
│   │   │   │   ├── 5.cpp
│   │   │   │   ├── 6.cpp
│   │   │   │   ├── 7-1.cpp
│   │   │   │   ├── 7.cpp
│   │   │   │   ├── 8.cpp
│   │   │   │   ├── 9-2.cpp
│   │   │   │   ├── 9.cpp
│   │   │   │   └── BUILD
│   │   │   └── readme.md
│   │   └── readme.md
│   └── key_exercises/
│       ├── BUILD
│       ├── README.md
│       ├── array.cpp
│       ├── array_template.cpp
│       ├── bracket_overloading.cpp
│       ├── clock.cpp
│       ├── func_temp.cpp
│       ├── io_operator.cpp
│       ├── io_operator_overload.cpp
│       ├── map_insert_look.cpp
│       ├── operator_cast.cpp
│       ├── operator_circle.cpp
│       ├── output.cpp
│       ├── override.cpp
│       ├── read_file.cpp
│       ├── stack.cpp
│       └── try.cpp
├── proj/
│   └── README.md
├── src_analysis/
│   └── stl/
│       ├── array.md
│       ├── deque.md
│       ├── hashtable.md
│       ├── iterator.md
│       ├── list.md
│       ├── map_multimap.md
│       ├── myhashtable.md
│       ├── queue_stack.md
│       ├── rb_tree.md
│       ├── set_multiset.md
│       ├── traits.md
│       ├── typename.md
│       ├── unordered_map.md
│       ├── vector.md
│       └── 谈谈STL设计之EBO优化.md
└── tool/
    ├── C++的Debug工具dbg-macro.md
    ├── output/
    │   ├── BUILD
    │   ├── container.cpp
    │   └── output_container.h
    ├── 像Python一样玩CC++.md
    └── 用rr来进行debug.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
com.sh
bazel-CPlusPlusThings
bazel-bin
bazel-out
bazel-testlogs
bazel-cplusplus_bazel
.vscode

================================================
FILE: README.md
================================================

- [C++ 那些事](#c-那些事)
    - [重磅项目](#重磅项目)
    - [关于作者](#关于作者)
    - [项目运行](#项目运行)
      - [方式1: vscode + bazel](#方式1-vscode--bazel)
      - [方式2: docker](#方式2-docker)
      - [方式3: g++](#方式3-g)
    - [视频学习本项目](#视频学习本项目)
    - [飞书知识库](#飞书知识库)
    - [基础进阶](#基础进阶)
    - [实战系列](#实战系列)
      - [10 日狂练](#10-日狂练)
      - [重点实战练习](#重点实战练习)
    - [C++2.0 新特性](#c20-新特性)
      - [概况](#概况)
      - [C++11 新特性](#c11-新特性)
      - [C++14/17/20](#c141720)
    - [设计模式](#设计模式)
    - [STL 源码剖析](#stl-源码剖析)
    - [并发编程](#并发编程)
      - [C++ Concurrency in Action](#c-concurrency-in-action)
      - [多线程与多进程](#多线程与多进程)
        - [Threading In C++](#threading-in-c)
    - [C++ 惯用法](#c-惯用法)
        - [你最喜欢的 c++ 编程风格惯用法是什么?](#你最喜欢的-c-编程风格惯用法是什么)
    - [学习课程](#学习课程)
      - [极客时间《现代 C++ 实战 30 讲》](#极客时间现代-c-实战-30-讲)
    - [工具篇](#工具篇)
      - [容器快捷输出工具](#容器快捷输出工具)
      - [像 Python 一样简单输出(Jupyter Notebook)](#像-python-一样简单输出jupyter-notebook)
      - [观察编译过程变化](#观察编译过程变化)
      - [C++ 的 Debug 工具 dbg-macro](#c-的-debug-工具-dbg-macro)
      - [在 Linux 上的 Debug 工具 rr - 拥有回到过去的能力](#在-linux-上的-debug-工具-rr---拥有回到过去的能力)
    - [拓展部分](#拓展部分)
      - [一些问题](#一些问题)
    - [贡献者](#贡献者)

# C++ 那些事


感谢各位对《C++ 那些事》的支持,现将内容也同步至B站,以视频的方式展示,可以打开网站直接阅读~欢迎大家 star、转发、PR。

在线个人博客:[光城的实验室](https://light-city.github.io/)

在线学习网站:[C++那些事](https://light-city.github.io/stories_things/)

- 中文名:**C++ 那些事**
- 英文名:**Stories About C Plus Plus**

这是一个适合初学者从<u>**入门到进阶**</u>的仓库,解决了<u>**面试者与学习者**</u>想要<u>**深入 C++**</u> 及如何<u>**入坑 C++**</u> 的问题。除此之外,本仓库拓展了更加深入的源码分析,多线程并发等的知识,是一个比较全面的 C++ 学习从入门到进阶提升的仓库。


### 重磅项目

推出一系列重磅项目,带大家实战学习C++,配合本开源项目学习,成长飞快!

直通点:[戳这里](./proj/README.md)

### 关于作者

公众号已开放两大入口,分别是专辑与菜单,可以直接在微信公众号上阅读《C++ 那些事》内容,配上该仓库的代码,将会非常的爽,建议大家关注一波。

个人公众号:guangcity

或者扫下面的二维码,欢迎大家反馈及 C++ 交流,本人在微信创建了 C++ 那些事交流群,优质的 C++ 资源交流区,期待大家关注上面公众号,点击公众号右下角->联系我,拉你入群。

---

>关注我

如果觉得不错,关注我吧~

<table>
  <tbody>
    <tr>
      <th align="center" style="height=200 width="200">
          <img src="./img/cpp.jpg" height="200" width="200" ><br>
          星球
      </th>
      <th align="center" style="height=200 width="200">
          <img src="./img/wechat.jpg" height="200" width="200" ><br>
          微信公众号
      </th>
    </tr>
  </tbody>
</table>


### 项目运行


#### 方式1: vscode + bazel

#### 方式2: docker

新推出免开发环境,docker环境,大家可以pull下面镜像:

```
docker pull xingfranics/cplusplusthings:latest
```
#### 方式3: g++


### 视频学习本项目

[第一期:Step By Step上手编译本项目](https://www.bilibili.com/video/BV1Rv4y1H7LB/?vd_source=bb6532dcd5b1d6b26125da900adb618e)

[第二期:免开发环境docker](https://www.bilibili.com/video/BV1oz4y1a7Pu/?vd_source=bb6532dcd5b1d6b26125da900adb618e)

[第三期:手把手共读HashTable,彻底搞懂C++ STL](https://www.bilibili.com/video/BV1o8411U7vy/?vd_source=bb6532dcd5b1d6b26125da900adb618e)

[第四期:手把手共读STL之enable_shared_from_this](https://www.bilibili.com/video/BV1du4y1w7Mg/?spm_id_from=333.788&vd_source=bb6532dcd5b1d6b26125da900adb618e)

[第五期:手把手共读STL之线程,从C++11 thread到C++20 jthread](https://www.bilibili.com/video/BV1DH4y1g7gS/?vd_source=bb6532dcd5b1d6b26125da900adb618e)

[第六期:手把手共读STL之共读condition_variable、condition_variable_any](https://www.bilibili.com/video/BV13b421b7Am/?spm_id_from=333.999.0.0&vd_source=bb6532dcd5b1d6b26125da900adb618e)

[第七期:手把手共读STL之Mutex](https://www.bilibili.com/video/BV1xm42157pq/?spm_id_from=333.999.0.0&vd_source=bb6532dcd5b1d6b26125da900adb618e)

[第八期:手把手共读STL之RAII Lock](https://www.bilibili.com/video/BV1Ls421g7iq/?spm_id_from=333.788&vd_source=bb6532dcd5b1d6b26125da900adb618e)

### 飞书知识库

[互联网大厂面试实录](https://hmpy6adnp5.feishu.cn/docx/OitBdRB4KozIhTxQt7Ec7iFDnkc)

[拿下offer之必备面经](https://hmpy6adnp5.feishu.cn/docx/B1aCdVTUgoyJGYxtWV7cdvgRnxv)


### 基础进阶

- [`const` 那些事](./basic_content/const)
- [`static` 那些事](./basic_content/static)
- [`this` 那些事](./basic_content/this)
- [`inline` 那些事](./basic_content/inline)
- [`sizeof` 那些事](./basic_content/sizeof)
- [函数指针那些事](./basic_content/func_pointer)
- [纯虚函数和抽象类那些事](./basic_content/abstract)
- [`vptr_vtable` 那些事](./basic_content/vptr_vtable)
- [`virtual` 那些事](./basic_content/virtual)
- [`volatile` 那些事](./basic_content/volatile)
- [`assert` 那些事](./basic_content/assert)
- [位域那些事](./basic_content/bit)
- [`extern` 那些事](./basic_content/extern)
- [`struct` 那些事](./basic_content/struct)
- [`struct` 与 `class` 那些事](./basic_content/struct_class)
- [`union` 那些事](./basic_content/union)
- [`c` 实现 `c++` 多态那些事](./basic_content/c_poly)
- [`explicit` 那些事](./basic_content/explicit)
- [`friend` 那些事](./basic_content/friend)
- [`using` 那些事](./basic_content/using)
- [`::` 那些事](./basic_content/maohao)
- [`enum` 那些事](./basic_content/enum)
- [`decltype` 那些事](./basic_content/decltype)
- [引用与指针那些事](./basic_content/pointer_refer)
- [宏那些事](./basic_content/macro)

### 实战系列

#### [10 日狂练](./practical_exercises/10_day_practice)

- [day1-基本语法](practical_exercises/10_day_practice/day1)

- [day2-递归、结构体、枚举、静态变量等](practical_exercises/10_day_practice/day2)

- [day3-函数1](practical_exercises/10_day_practice/day3)

- [day4-函数2](practical_exercises/10_day_practice/day4)

- [day5-继承多态](practical_exercises/10_day_practice/day5)

- [day6-虚函数与抽象类](practical_exercises/10_day_practice/day6)

- [day7-运算符重载](practical_exercises/10_day_practice/day7)

- [day8-模版与STL](practical_exercises/10_day_practice/day8)

- [day9-异常](practical_exercises/10_day_practice/day9)

- [day10-文件与流](practical_exercises/10_day_practice/day10)

#### [重点实战练习](./practical_exercises/key_exercises/)

- [中括号重载.cpp](./practical_exercises/key_exercises/bracket_overloading.cpp)

- [时钟++运算符重载.cpp](./practical_exercises/key_exercises/clock.cpp)

- [运算符重载之强制转换.cpp](./practical_exercises/key_exercises/operator_cast.cpp)

- [重载圆括号的时钟.cpp](./practical_exercises/key_exercises/operator_circle.cpp)

- [函数模板.cpp](./practical_exercises/key_exercises/func_temp.cpp)

- [动态数组.cpp](./practical_exercises/key_exercises/array.cpp)

- [字典插入与查找.cpp](./practical_exercises/key_exercises/map_insert_look.cpp)

- [异常捕获.cpp](./practical_exercises/key_exercises/try.cpp)

- [类模板之栈.cpp](./practical_exercises/key_exercises/stack.cpp)

- [类模板特化之数组.cpp](./practical_exercises/key_exercises/array_template.cpp)

- [继承与封装.cpp](./practical_exercises/key_exercises/override.cpp)

- [读写文件综合题.cpp](./practical_exercises/key_exercises/read_file.cpp)

- [输入输出运算符重载.cpp](./practical_exercises/key_exercises/io_operator_overload.cpp)

- [输入输出重载.cpp](./practical_exercises/key_exercises/io_operator.cpp)

- [输出格式.cpp](./practical_exercises/key_exercises/output.cpp)


### [C++2.0 新特性](./cpp2.0)

#### 概况

C++2.0 是一个简称,意为「现代 C++」,包括 C++11/14/17/20。

#### [C++11 新特性](./cpp2.0/cpp11)

- [Variadic Templates](./cpp2.0/cpp11/variadic)

- Spaces in Template Expressions

  ```cpp
  vector<list<int> > //ok in each C++ version
  vector<list<int>> // before c++ 11 error error: ‘>>’ should be ‘> >’ within a nested template argument list,c++11后可以正常通过
  ```

- [nullptr and nullptr_t](./cpp2.0/cpp11/nullptr.cpp)

- [Automatic Type Deduction with auto](./cpp2.0/cpp11/auto.cpp)

- [Uniform Initialization ](./cpp2.0/cpp11/uniform_initialization.cpp)

- [initializer_list](./cpp2.0/cpp11/initializer.cpp)

- [explicit for ctors taking more than one argument](./cpp2.0/cpp11/explicit.cpp)

- [range-based for statement](./cpp2.0/cpp11/auto.cpp)

  ```cpp
  for(decl:col) {
      statement
  }
  ```

- [=default,=delete](./cpp2.0/cpp11/default_delete.cpp)

  如果你自行定义了一个 `ctor`, 那么编译器就不会给你一个 `default ctor`
  如果强制加上 `=default`, 就可以重新获得并使用 `default ctor`.

- Alias(化名) Template (template typedef)

  - [alias.cpp](./cpp2.0/cpp11/alias.cpp)
  - [template_template.cpp](./cpp2.0/cpp11/template_template.cpp)

- [template template parameter](./cpp2.0/template_template.cpp)

- [type alias](./cpp2.0/cpp11/type_alias.cpp)

- [noexcept](./cpp2.0/cpp11/noexcept.cpp)

- [override](./cpp2.0/cpp11/override.cpp)

- [final](./cpp2.0/cpp11/final.cpp)

- [decltype](./cpp2.0/cpp11/decltype.cpp)

- [lambda](./cpp2.0/cpp11/lambda.cpp)

- [Rvalue reference](./cpp2.0/cpp11/rvalue.cpp)

- [move aware class](./cpp2.0/cpp11/move.cpp)

- 容器-结构与分类

  - (1) 序列式容器包括:`array`(C++2.0 新引入),`vector`,`deque`,`list`,`forward_list`(C++2.0 新引入)
  - (2) 关联式容器包括:`set/multiset`,`map/multimap`
  - (3) 无序容器(C++2.0 新引入,更换原先 `hash_xxx` 为 `unordered_xxx`)包括:`unordered_map/unordered_multimap,unordered_set/unordered_multiset`

- [Hash Function](./cpp2.0/cpp11/hash.cpp)

- [tuple](./cpp2.0/cpp11/tuple.cpp)

  学习资料:https://www.bilibili.com/video/av51863195?from=search&seid=3610634846288253061

#### C++14/17/20

待更新...

### 设计模式

- [单例模式](./design_pattern/singleton)
- [生产消费者模式](./design_pattern/producer_consumer)

### [STL 源码剖析](./src_analysis/stl)

**STL 源码剖析:gcc 4.9.1**

- [array](./src_analysis/stl/array.md)
- [deque](./src_analysis/stl/deque.md)
- [queue and stack](./src_analysis/stl/queue_stack.md)
- [list](./src_analysis/stl/list.md)
- [vector](./src_analysis/stl/vector.md)
- [typename](./src_analysis/stl/typename.md)
- [traits](./src_analysis/stl/traits.md)
- [iterator](./src_analysis/stl/iterator.md)
- [谈谈 STL 设计之 EBO 优化](./src_analysis/stl/谈谈STL设计之EBO优化.md)
- [rb_tree](./src_analysis/stl/rb_tree.md)
- [set and multiset](./src_analysis/stl/set_multiset.md)
- [map and multimap](./src_analysis/stl/map_multimap.md)
- [hashtable](./src_analysis/stl/hashtable.md)
- [myhashtable](./src_analysis/stl/myhashtable.md)
- [unordered_map](./src_analysis/stl/unordered_map.md)

### [并发编程](./concurrency)

#### C++ Concurrency in Action

- [第一章](./concurrency/concurrency_v1/chapter1)
- [第二章](./concurrency/concurrency_v1/chapter2)

学习资料:https://downdemo.gitbook.io/cpp-concurrency-in-action-2ed/

#### 多线程与多进程

##### Threading In C++

- [介绍](./concurrency/Threading_In_CPlusPlus/1.thread)
- [创建线程的五种类型](./concurrency/Threading_In_CPlusPlus/2.create_type)
- [Join 与 Detachs](./concurrency/Threading_In_CPlusPlus/3.join_detach)
- [mutex in C++ Threading](./concurrency/Threading_In_CPlusPlus/4.mutex)

> 学习自:
>
> https://www.youtube.com/watch?v=eZ8yKZo-PGw&list=PLk6CEY9XxSIAeK-EAh3hB4fgNvYkYmghp&index=4

### [C++ 惯用法](./codingStyleIdioms)

##### 你最喜欢的 c++ 编程风格惯用法是什么?

- [1.类初始化列表](./codingStyleIdioms/1_classInitializers)
- [2.枚举类替换命名空间](./codingStyleIdioms/2_enumclass_namespace)
- [3.RAII (资源获取即初始化)](./codingStyleIdioms/3_RAII)
- [4.copy and swap](./codingStyleIdioms/4_copy-swap)
- [5.pImpl (指针指向具体实现)](./codingStyleIdioms/5_pImpl)

### 学习课程

#### [极客时间《现代 C++ 实战 30 讲》](https://time.geekbang.org/channel/home)

- [堆、栈、RAII:C++ 里该如何管理资源?](./learn_class/modern_cpp_30/RAII)
  - [堆](./learn_class/modern_++_30/RAII/heap.cpp)
  - [栈](./learn_class/modern_cpp_30/RAII/stack.cpp)
  - [RAII](./learn_class/modern_cpp_30/RAII/RAII.cpp)
- [自己动手,实现 C++ 的智能指针](./learn_class/modern_cpp_30/smart_ptr)
  - [auto_ptr、scope_ptr](./learn_class/modern_cpp_30/smart_ptr/auto_scope.cpp)
  - [unique_ptr](./learn_class/modern_cpp_30/smart_ptr/unique_ptr.cpp)
  - [shared_ptr](./learn_class/modern_cpp_30/smart_ptr/shared_ptr.cpp)
- [右值和移动究竟解决了什么问题?](./learn_class/modern_cpp_30/reference)
  - [左值与右值](./learn_class/modern_cpp_30/reference/reference.cpp)
  - [延长声明周期](./learn_class/modern_cpp_30/reference/lifetime.cpp)
  - [引用折叠](./learn_class/modern_cpp_30/reference/collapses.cpp)
  - [完美转发](./learn_class/modern_cpp_30/reference/forward.cpp)
  - [不要返回本地变量的引用](./learn_class/modern_cpp_30/reference/don'treturnReference.cpp)
- [容器 1](./learn_class/modern_cpp_30/container1)
- [容器 2](./learn_class/modern_cpp_30/container2)
- [异常](./learn_class/modern_cpp_30/exception)
- [字面量、静态断言和成员函数说明符](./learn_class/modern_cpp_30/literalAssert)
- [是不是应该返回对象?](./learn_class/modern_cpp_30/returnObj)
- [编译期多态:泛型编程和模板入门](./learn_class/modern_cpp_30/compilerpoly)
- [译期能做些什么?一个完整的计算世界](./learn_class/modern_cpp_30/compilercompute)
- [SFINAE:不是错误的替换失败是怎么回事?](./learn_class/modern_cpp_30/SFINAE)
- [constexpr:一个常态的世界](./learn_class/modern_cpp_30/constexpr)
- [函数对象和 lambda:进入函数式编程](./learn_class/modern_cpp_30/functionLambda)
- [内存模型和 atomic:理解并发的复杂性](./learn_class/modern_cpp_30/memorymodel_atomic)

### 工具篇

#### [容器快捷输出工具](./tool/output)

对吴老师的代码进行了修改,[点击此处直通代码](./tool/output/output_container.h)

输入:

```cpp
map<int, int> mp{
            {1, 1},
            {2, 4},
            {3, 9}};
    cout << mp << endl;
```

输出结果显示:

```cpp
{ 1 => 1, 2 => 4, 3 => 9 }
```

#### 像 Python 一样简单输出(Jupyter Notebook)

- [像 Python 一样玩 C/C++](./tool/像Python一样玩CC++.md)

#### 观察编译过程变化

-  [https://cppinsights.io](https://cppinsights.io/)

#### C++ 的 Debug 工具 dbg-macro

- [C++ 的 Debug 工具 dbg-macro](./tool/C++的Debug工具dbg-macro.md)

#### 在 Linux 上的 Debug 工具 rr - 拥有回到过去的能力
- [用 rr 来进行 debug](./tool/用rr来进行debug.md)

### 拓展部分

#### 一些问题

- [C++ 中如何将 string 类型转换为 int 类型?](./extension/some_problem/string_int.md)

### 贡献者



| 贡献人  | 地址                          |
| ------- | ----------------------------- |
| 光城    | https://github.com/Light-City |
| ChungZH | https://github.com/ChungZH    |
| xliu79  | https://github.com/xliu79     |







================================================
FILE: README_EN.md
================================================
# Stories About C Plus Plus

Thanks for all the support about << Stories About C ++ >>~~, right now you could open this link(https://light-city.club/sc/) to read this article.~~
Any star, retweet or pr will be welcomed.

**Notice: The website is not available now.**


-----------------------


### 0. Directory

- Chinese version:**C++ 那些事**
- English version:**Stories About C Plus Plus**

This repository meets the need of people who wants to really know about C++, and may help you in the interview. Besides, it also provides
other details,such as in-depth source code analysis and multi-threaded concurrency. It is a comprehensive C ++ repository from entry to advanced improvement

### 1.Foundation

- [Stories About const](./basic_content/const)
- [Stories About static](./basic_content/static)
- [Stories about this](./basic_content/this)
- [Stories About inline](./basic_content/inline)
- [Stories About sizeof](./basic_content/sizeof)
- [Stories About pointer of function](./basic_content/func_pointer)
- [Stories About pure virtual function and abstract](./basic_content/abstract)
- [Stories About vptr_vtable](./basic_content/vptr_vtable)
- [Stories About virtual](./basic_content/virtual)
- [Stories About volatile](./basic_content/volatile)
- [Stories About assert](./basic_content/assert)
- [Stories About bit](./basic_content/bit)
- [Stories About extern](./basic_content/extern)
- [Stories About struct](./basic_content/struct)
- [Stories About struct and class](./basic_content/struct_class)
- [Stories About union](./basic_content/union)
- [Stories About polymorphism](./basic_content/c_poly)
- [Stories About explicit](./basic_content/explicit)
- [Stories About friend](./basic_content/friend)
- [Stories About using](./basic_content/using)
- [Stories About :: ](./basic_content/maohao)
- [Stories About enum](./basic_content/enum)
- [Stories About decltype](./basic_content/decltype)
- [Stories About pointer_refer](./basic_content/pointer_refer)
- [Stories About macro](./basic_content/macro)

### 2.Code Samples

#### 2.1 10 Days Practice

- [x] day1

Basic Grammar About C ++
- [x] day2

Recursive、Struct、Enumerate、Static Variable

- [x] day3

Function

- [x] day4

Thorough About Function 

- [x] day5

Inheritance and Polymorphism 

- [x] day6

Virtual Function、Abstruct 

- [x] day7

Operator overloading

- [x] day8

Template And STL

- [x] day9

Exception

- [x] day10

File And Stream

#### 2.2 Practical Exercises

├── [Square brackets overload .cpp](./practical_exercises/key_exercises/中括号重载.cpp)
├── [Clock++operator overloading.cpp](./practical_exercises/key_exercises/时钟++运算符重载.cpp)
├── [Mandatory conversion of operator overloading.cpp](./practical_exercises/key_exercises/运算符重载之强制转换.cpp)
└── [Clock with overloaded parenthesis.cpp](./practical_exercises/key_exercises/重载圆括号的时钟.cpp)

├── [Template of Function.cpp](./practical_exercises/key_exercises/函数模板.cpp)

├── [Dynamic array.cpp](./practical_exercises/key_exercises/动态数组.cpp)

├── [Dictionary insertion and search.cpp](./practical_exercises/key_exercises/字典插入与查找.cpp)

├── [Catch Exception.cpp](./practical_exercises/key_exercises/异常捕获.cpp)

├── [Template of Stack.cpp](./practical_exercises/key_exercises/类模板之栈.cpp)

├── [Template of Array.cpp](./practical_exercises/key_exercises/类模板特化之数组.cpp)

├── [Inheritance And Package.cpp](./practical_exercises/key_exercises/继承与封装.cpp)

├── [Read And Write files.cpp](./practical_exercises/key_exercises/读写文件综合题.cpp)
├── [Operator Overloading About Input and Output.cpp](./practical_exercises/key_exercises/输入输出运算符重载.cpp)
├── [Input And Output Overloading.cpp](./practical_exercises/key_exercises/输入输出重载.cpp)
├── [Input Format.cpp](./practical_exercises/key_exercises/输出格式.cpp)

### 2.[C++2.0 New Features](./c++2.0)

#### 2.0 Overview

C++2.0 is an Abbreviation, meaning「modern C++」,including C++11/14/17/20.

#### 2.1 [C++11 New Features](./c++2.0/c++11)

- [Variadic Templates](./c++2.0/variadic)

- Spaces in Template Expressions

  ```cpp
  vector<list<int> > //ok in each C++ version
  vector<list<int>> // before c++ 11 error error: ‘>>’ should be ‘> >’ within a nested template argument list,version beyond c++ 11 could   compile successfully
  ```

- [nullptr and nullptr_t](./c++2.0/nullptr.cpp)

- [Automatic Type Deduction with auto](./c++2.0/auto.cpp)

- [Uniform Initialization ](./c++2.0/uniform_initialization.cpp)

- [initializer_list](./c++2.0/initializer.cpp)

- [explicit for ctors taking more than one argument](./c++2.0/explicit.cpp)

- [range-based for statement](./c++2.0/auto.cpp)

  ```cpp
  for(decl:col) {
      statement
  }
  ```

- [=default,=delete](./c++2.0/default_delete.cpp)

  If you define a ctor by yourself, compiler won't compile the default ctor.
  If you add =default, you could recatch and use default ctor.

- Alias(化名)Template(template typedef)

  - [alias.cpp](./c++2.0/alias.cpp) 
  - [template_template.cpp](./c++2.0/template_template.cpp)

- [template template parameter](./c++2.0/template_template.cpp)

- [type alias](./c++2.0/type_alias.cpp)

- [noexcept](./c++2.0/noexcept.cpp)

- [override](./c++2.0/override.cpp)

- [final](./c++2.0/final.cpp)

- [decltype](./c++2.0/decltype.cpp)

- [lambda](./c++2.0/lambda.cpp)

- [Rvalue reference](./c++2.0/rvalue.cpp)

- [move aware class](./c++2.0/move.cpp)

- Container-Struct And Classify

  - (1) Serial containers include:`array`(C++2.0 Newly Introduced),`vector`,`deque`,`list`,`forward_list`(C++2.0 Newly Introduced)
  - (2) Associated containers include:`set/multiset`,`map/multimap`
  - (3) Unordered container(C++2.0 Newly Introduced,replace `hash_xxx` to `unordered_xxx`) include:`unordered_map/unordered_multimap,unordered_set/unordered_multiset`

- [Hash Function](./c++2.0/hash.cpp)

- [tuple](./c++2.0/tuple.cpp)

  Learning Material:https://www.bilibili.com/video/av51863195?from=search&seid=3610634846288253061

### 2.2 C++14/17/20

To Be Continued ...

### 3.Design Pattern

- [Singleton pattern](./design_pattern/singleton)

### 4. [STL Source Code Analysis](./src_analysis/stl)

**STL Source Code Analysis:gcc 4.9.1**

- [array](./src_analysis/stl/array.md)
- [deque](./src_analysis/stl/deque.md)
- [queue and stack](./src_analysis/stl/queue_stack.md)
- [list](./src_analysis/stl/list.md)
- [vector](./src_analysis/stl/vector.md)
- [typename](./src_analysis/stl/typename.md)
- [traits](./src_analysis/stl/traits.md)
- [iterator](./src_analysis/stl/iterator.md)
- [Talking about STL design and EBO optimization](./src_analysis/stl/谈谈STL设计之EBO优化.md)
- [rb_tree](./src_analysis/stl/rb_tree.md)
- [set and multiset](set_multiset.md)
- [map and multimap](./src_analysis/stl/map_multimap.md)
- [hashtable](./src_analysis/stl/hashtable.md)
- [myhashtable](./src_analysis/stl/myPhashtable.md)
- [unordered_map](./src_analysis/stl/unordered_map.md)

### 4. [Concurrent Programming](./concurrency)

#### 4.1 C++ Concurrency in Action

- [Chapter One](./concurrency/concurrency_v1/chapter1)
- [Chapter Two](./concurrency/concurrency_v1/chapter2)

Learning materials: https://chenxiaowei.gitbook.io/cpp_concurrency_in_action/

#### 4.2 Multithreading And Multiprocess

##### 4.2.1 Threading In C++

- [Introduction](./concurrency/Threading_In_CPlusPlus/1.thread)
- [Five Types of Thread Creation](./concurrency/Threading_In_CPlusPlus/2.create_type)
- [Join And Detaches](./concurrency/Threading_In_CPlusPlus/3.join_detach)
- [mutex in C++ Threading](./concurrency/Threading_In_CPlusPlus/4.mutex)

> From:
>
> https://www.youtube.com/watch?v=eZ8yKZo-PGw&list=PLk6CEY9XxSIAeK-EAh3hB4fgNvYkYmghp&index=4

### 5. [C++ Conventional method](./codingStyleIdioms)

##### What is your favorite custom for c ++ programming style?

- [1.ClassInitializers](./codingStyleIdioms/1_classInitializers)
- [2.Replace Enumclass with Namespace](./codingStyleIdioms/2_enumclass_namespace)
- [3.RAII(Resource Acquisition Initialization)](./codingStyleIdioms/3_RAII)
- [4.Copy and Swap](./codingStyleIdioms/4_copy-swap)
- [5.pImpl(Pointer Implement)](./codingStyleIdioms/5_pImpl)

### 6.Learning Courses

#### 6.1 [Chinese Name:极客时间《现代 C++ 实战 30 讲》](https://time.geekbang.org/channel/home)

- [heap、stack、RAII:How to manage resources for C ++ ?](./learn_class/modern_cpp_30/RAII)
  - [heap](./modern_++_30/RAII/heap.cpp)
  - [stack](./learn_class/modern_cpp_30/RAII/stack.cpp)
  - [RAII](./learn_class/modern_cpp_30/RAII/RAII.cpp)
- [Implementing smart pointers for C ++](./learn_class/modern_cpp_30/smart_ptr)
  - [auto_ptr、scope_ptr](./learn_class/modern_cpp_30/smart_ptr/auto_scope.cpp)
  - [unique_ptr](./learn_class/modern_cpp_30/smart_ptr/unique_ptr.cpp)
  - [shared_ptr](./learn_class/modern_cpp_30/smart_ptr/shared_ptr.cpp)
- [What exactly does r value and move solve?](./learn_class/modern_cpp_30/reference)
  - [L value and R value](./learn_class/modern_cpp_30/reference/reference.cpp)
  - [Extend the declaration cycle](./learn_class/modern_cpp_30/reference/lifetime.cpp)
  - [Reference folding](./learn_class/modern_cpp_30/reference/collapses.cpp)
  - [Perfect forward](./learn_class/modern_cpp_30/reference/forward.cpp)
  - [Do not return Reference](./learn_class/modern_cpp_30/reference/don'treturnReference.cpp)
- [Container 1](./learn_class/modern_cpp_30/container1)
- [Container 2](./learn_class/modern_cpp_30/container2)
- [Exception](./learn_class/modern_cpp_30/exception)
- [Literal、Static Assertion And Member Function Specifier](./learn_class/modern_cpp_30/literalAssert)
- [Return Object?](./learn_class/modern_cpp_30/returnObj)c
- [Getting started with generic programming and templates](./learn_class/modern_cpp_30/compilerpoly)
- [A whole Compiler Compute World](./learn_class/modern_cpp_30/compilercompute)
- [SFINAE:What is it if it is not replace error?](./learn_class/modern_cpp_30/SFINAE)
- [constexpr:A Normal World](./learn_class/modern_cpp_30/constexpr)
- [Function object and Lambda:functionLambda](./learn_class/modern_cpp_30/functionLambda)
- [Memory Model and Atomic:Understanding the complexity of concurrency](./learn_class/modern_cpp_30/memorymodel_atomic)

### 7.Tools

#### 7.1 [Container shortcut output tool](./tool/output)

Modified the code, [Click here for the code](./tool/output/output_container.h)

Input:

```cpp
map<int, int> mp{
            {1, 1},
            {2, 4},
            {3, 9}};
    cout << mp << endl;
```

Output:

```cpp
{ 1 => 1, 2 => 4, 3 => 9 }
```

#### 7.2 Output Like Python(Jupyter Notebook)

- [How to output like python in C/C++](./tool/像Python一样玩CC++.md)

#### 7.3 Observe the changes in the compilation process

-  [https://cppinsights.io](https://cppinsights.io/)

#### 7.4 Debug Tools For C ++:dbg-macro

- [Debug Tool: dbg-macro](./tool/C++的Debug工具dbg-macro.md)

### 8.Expansion

#### 8.1 Other Problems
- [How to convert string to in C ++?](./extension/some_problem/string_int.md)


### 9.Circumstance


- **Running Circumstance**

  Ubuntu 18.04

- **IDE**

  CLion  gcc/g++

### 10.Contributor



| 贡献人  | 地址                          |
| ------- | ----------------------------- |
| 光城    | https://github.com/Light-City |
| ChungZH | https://github.com/ChungZH    |
| xliu79  | https://github.com/xliu79     |



### 11.About The Writer

个人公众号:

![](./img/wechat.jpg)


================================================
FILE: WORKSPACE
================================================


================================================
FILE: basic_content/abstract/BUILD
================================================
# you can run some main program, just replace binary name
# such as: `bazel run basic_content/abstract:interesting_facts1`
#          `bazel run basic_content/abstract:interesting_facts2`
# etc...
load("@rules_cc//cc:defs.bzl", "cc_binary")

# Don't panic if you get compilation errors, this is what this code demonstrates, as expected.
cc_binary(
    name = "interesting_facts1",
    srcs = ["interesting_facts1.cpp"],
)

cc_binary(
    name = "interesting_facts2",
    srcs = ["interesting_facts2.cpp"],
)

# Don't panic if you get compilation errors, this is what this code demonstrates, as expected.
cc_binary(
    name = "interesting_facts3",
    srcs = ["interesting_facts3.cpp"],
)

cc_binary(
    name = "interesting_facts4",
    srcs = ["interesting_facts4.cpp"],
)

cc_binary(
    name = "interesting_facts5",
    srcs = ["interesting_facts5.cpp"],
)

# Don't panic if you get compilation errors, this is what this code demonstrates, as expected.
cc_binary(
    name = "pure_virtual",
    srcs = ["pure_virtual.cpp"],
)

cc_binary(
    name = "derived_full",
    srcs = ["derived_full.cpp"],
)

================================================
FILE: basic_content/abstract/README.md
================================================
# 纯虚函数和抽象类

## 关于作者:

个人公众号:

![](../img/wechat.jpg)

## 1.纯虚函数与抽象类

C++中的纯虚函数(或抽象函数)是我们没有实现的虚函数!我们只需声明它! 通过声明中赋值0来声明纯虚函数!
```cpp
// 抽象类
Class A {
public: 
    virtual void show() = 0; // 纯虚函数
    /* Other members */
}; 
```

 * 纯虚函数:没有函数体的虚函数
 * 抽象类:包含纯虚函数的类

抽象类只能作为基类来派生新类使用,不能创建抽象类的对象,抽象类的指针和引用->由抽象类派生出来的类的对象!

> 代码样例:[abstract_base.h](./abstract_base.h)、[pure_virtual.cpp](./pure_virtual.cpp)

## 2.实现抽象类

抽象类中:在成员函数内可以调用纯虚函数,在构造函数/析构函数内部不能使用纯虚函数。

如果一个类从抽象类派生而来,它必须实现了基类中的所有纯虚函数,才能成为非抽象类。
```cpp
// A为抽象类
class A {
public:
    virtual void f() = 0;  // 纯虚函数
    void g(){ this->f(); }
    A(){}  // 构造函数
};

class B : public A{
public:
    void f(){ cout<<"B:f()"<<endl;}  // 实现了抽象类的纯虚函数
};
```

> 代码样例:[abstract.cpp](./abstract.cpp)

## 3.重要点

- [纯虚函数使一个类变成抽象类](./interesting_facts1.cpp)
```cpp
// 抽象类至少包含一个纯虚函数
class Base{
public: 
    virtual void show() = 0; // 纯虚函数
    int getX() { return x; } // 普通成员函数

private:
     int x; 
}; 
```

- [抽象类类型的指针和引用](./interesting_facts2.cpp)
```cpp
class Derived : public Base { 
public: 
    void show() { cout << "In Derived \n"; } // 实现抽象类的纯虚函数
    Derived(){} // 构造函数
}; 

int main(void) 
{ 
    //Base b;  // error! 不能创建抽象类的对象
    //Base *b = new Base(); error!
    
    Base *bp = new Derived(); // 抽象类的指针和引用 -> 由抽象类派生出来的类的对象
    bp->show();
    return 0; 
}
```

- [如果我们不在派生类中覆盖纯虚函数,那么派生类也会变成抽象类](./interesting_facts3.cpp)
```cpp
// Derived为抽象类
class Derived: public Base 
{ 
public: 
//    void show() {}
}; 
```

- [抽象类可以有构造函数](./interesting_facts4.cpp)
```cpp
// 抽象类
class Base { 
    protected: 
        int x; 
    public: 
        virtual void fun() = 0; 
        Base(int i) { x = i; }  // 构造函数
}; 
// 派生类
class Derived: public Base 
{ 
    int y; 
public: 
    Derived(int i, int j) : Base(i) { y = j; } // 构造函数
    void fun() { cout << "x = " << x << ", y = " << y; }
}; 
```

- [构造函数不能是虚函数,而析构函数可以是虚析构函数](./interesting_facts5.cpp)
```cpp
// 抽象类
class Base  {
public:
    Base(){ cout << "Constructor: Base" << endl; }
    virtual ~Base(){ cout << "Destructor : Base" << endl; }
    
    virtual void func() = 0;
};

class Derived: public Base {
public:
    Derived(){ cout << "Constructor: Derived" << endl; }
    ~Derived(){ cout << "Destructor : Derived" << endl;}
    
    void func(){cout << "In Derived.func()." << endl;}
};
```
>当基类指针指向派生类对象并删除对象时,我们可能希望调用适当的析构函数。
> 如果析构函数不是虚拟的,则只能调用基类析构函数。

## 4.完整实例

抽象类由派生类继承实现!

> 代码样例:[derived_full.cpp](./derived_full.cpp)

================================================
FILE: basic_content/abstract/abstract.cpp
================================================
/**
 * @file abstract.cpp
 * @brief
 * 抽象类中:在成员函数内可以调用纯虚函数,在构造函数/析构函数内部不能使用纯虚函数
 * 如果一个类从抽象类派生而来,它必须实现了基类中的所有纯虚函数,才能成为非抽象类
 * @author 光城
 * @version v1
 * @date 2019-07-20
 */

#include <iostream>
using namespace std;

class A {
public:
  virtual void f() = 0; // 纯虚函数
  void g() { this->f(); }
  A() {}
};
class B : public A {
public:
  void f() { cout << "B:f()" << endl; }
};
int main() {
  B b;
  b.g();
  return 0;
}


================================================
FILE: basic_content/abstract/abstract_base.h
================================================
/**
 * @file abstreact_base.cpp
 * @brief
 * C++中的纯虚函数(或抽象函数)是我们没有实现的虚函数!我们只需声明它!通过声明中赋值0来声明纯虚函数!
 * 纯虚函数:没有函数体的虚函数
 * @author 光城
 * @version v1
 * @date 2019-07-20
 */

/**
 * @brief 抽象类
 */
class AbstractBase {
  // Data members of class
public:
  // Pure Virtual Function
  virtual void show() = 0;

  /* Other members */
};


================================================
FILE: basic_content/abstract/derived_full.cpp
================================================
/**
 * @file derived_full.cpp
 * @brief 完整示例!抽象类由派生类继承实现!
 * @author 光城
 * @version v1
 * @date 2019-07-20
 */

#include <iostream>
using namespace std;

class Base {
  int x;

public:
  virtual void fun() = 0;
  int getX() { return x; }
};

class Derived : public Base {
public:
  void fun() { cout << "fun() called"; } // 实现了fun()函数
};

int main(void) {
  Derived d;
  d.fun();
  return 0;
}


================================================
FILE: basic_content/abstract/interesting_facts1.cpp
================================================
/**
 * @file interesting_facts1.cpp
 * @brief 纯虚函数使一个类变成抽象类
 * @author 光城
 * @version v1
 * @date 2019-07-20
 */

#include <iostream>
using namespace std;

/**
 * @brief 抽象类至少包含一个纯虚函数
 */
class Test {
  int x;

public:
  virtual void show() = 0;
  int getX() { return x; }
};

int main(void) {
  Test t; // error! 不能创建抽象类的对象
  return 0;
}


================================================
FILE: basic_content/abstract/interesting_facts2.cpp
================================================
/**
 * @file interesting_facts2.cpp
 * @brief 抽象类类型的指针和引用
 * @author 光城
 * @version v1
 * @date 2019-07-20
 */

#include <iostream>
using namespace std;

/**
 * @brief 抽象类至少包含一个纯虚函数
 */
class Base {
  int x;

public:
  virtual void show() = 0;
  int getX() { return x; }
};
class Derived : public Base {
public:
  void show() { cout << "In Derived \n"; }
  Derived() {}
};
int main(void) {
  // Base b;  //error! 不能创建抽象类的对象
  // Base *b = new Base(); error!
  Base *bp = new Derived(); // 抽象类的指针和引用 -> 由抽象类派生出来的类的对象
  bp->show();
  return 0;
}


================================================
FILE: basic_content/abstract/interesting_facts3.cpp
================================================
/**
 * @file interesting_facts3.cpp
 * @brief 如果我们不在派生类中覆盖纯虚函数,那么派生类也会变成抽象类。
 * @author 光城
 * @version v1
 * @date 2019-07-20
 */

#include <iostream>
using namespace std;

class Base {
  int x;

public:
  virtual void show() = 0;
  int getX() { return x; }
};
class Derived : public Base {
public:
  //    void show() { }
};
int main(void) {
  Derived
      d; // error!
         // 派生类没有实现纯虚函数,那么派生类也会变为抽象类,不能创建抽象类的对象
  return 0;
}


================================================
FILE: basic_content/abstract/interesting_facts4.cpp
================================================
/**
 * @file interesting_facts4.cpp
 * @brief 抽象类可以有构造函数
 * @author 光城
 * @version v1
 * @date 2019-07-20
 */

#include <iostream>
using namespace std;

// An abstract class with constructor
class Base {
protected:
  int x;

public:
  virtual void fun() = 0;
  Base(int i) { x = i; }
};

class Derived : public Base {
  int y;

public:
  Derived(int i, int j) : Base(i) { y = j; }
  void fun() { cout << "x = " << x << ", y = " << y; }
};

int main(void) {
  Derived d(4, 5);
  d.fun();
  return 0;
}


================================================
FILE: basic_content/abstract/interesting_facts5.cpp
================================================

/**
 * @file interesting_facts5.cpp
 * @brief 构造函数不能是虚函数,而析构函数可以是虚析构函数。
 * 例如:当基类指针指向派生类对象并删除对象时,我们可能希望调用适当的析构函数。如果析构函数不是虚拟的,则只能调用基类析构函数。
 * @author 光城
 * @version v1
 * @date 2019-07-20
 */
#include <iostream>
using namespace std;

class Base {
public:
  Base() { cout << "Constructor: Base" << endl; }
  virtual ~Base() { cout << "Destructor : Base" << endl; }
};

class Derived : public Base {
public:
  Derived() { cout << "Constructor: Derived" << endl; }
  ~Derived() { cout << "Destructor : Derived" << endl; }
};

int main() {
  Base *Var = new Derived();
  delete Var;
  return 0;
}


================================================
FILE: basic_content/abstract/pure_virtual.cpp
================================================
/**
 * @file pure_virtual.cpp
 * @brief 纯虚函数:没有函数体的虚函数
 * 抽象类:包含纯虚函数的类
 *
 * @author 光城
 * @version v1
 * @date 2019-07-20
 */

#include <iostream>

using namespace std;
class A {
private:
  int a;

public:
  virtual void show() = 0; // 纯虚函数
};

int main() {
  /*
   * 1. 抽象类只能作为基类来派生新类使用
   * 2. 抽象类的指针和引用->由抽象类派生出来的类的对象!
   */
  A a; // error 抽象类,不能创建对象

  A *a1; // ok 可以定义抽象类的指针

  A *a2 = new A(); // error, A是抽象类,不能创建对象
}


================================================
FILE: basic_content/assert/BUILD
================================================
# you can run some main program, just replace binary name
# such as: `bazel run basic_content/assert:ignore_assert`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "ignore_assert",
    srcs = ["ignore_assert.c"],
)

cc_binary(
    name = "assert",
    srcs = ["assert.c"],
)


================================================
FILE: basic_content/assert/README.md
================================================
# assert那些事

## 关于作者:

个人公众号:

![](../img/wechat.jpg)



## 1.第一个断言案例

断言,**是宏,而非函数**。

assert 宏的原型定义在 <assert.h>(C)、<cassert>(C++)中。其作用是如果它的条件返回错误,则终止程序执行。

可以通过定义 `NDEBUG` 来关闭 assert,**但是需要在源代码的开头,include <assert.h> 之前。**

```c
void assert(int expression);
```

> 代码样例:[assert.c](./assert.c)
```c
#include <stdio.h> 
#include <assert.h> 

int main() 
{ 
    int x = 7; 

    /*  Some big code in between and let's say x  
    is accidentally changed to 9  */
    x = 9; 

    // Programmer assumes x to be 7 in rest of the code 
    assert(x==7); 

    /* Rest of the code */

    return 0; 
} 
```
输出:
```c
assert: assert.c:13: main: Assertion 'x==7' failed.
```
可以看到输出会把源码文件,行号错误位置,提示出来!

## 2.断言与正常错误处理

+ 断言主要用于检查逻辑上不可能的情况。

>例如,它们可用于检查代码在开始运行之前所期望的状态,或者在运行完成后检查状态。与正常的错误处理不同,断言通常在运行时被禁用。

+ 忽略断言,在代码开头加上:
```c++
#define NDEBUG          // 加上这行,则 assert 不可用
```

> 样例代码:[ignore_assert.c](./ignore_assert.c)


================================================
FILE: basic_content/assert/assert.c
================================================
#include <stdio.h> 
#include <assert.h> 

int main() 
{ 
    int x = 7; 

    /*  Some big code in between and let's say x  
     *  is accidentally changed to 9  
     */
    x = 9; 

    // Programmer assumes x to be 7 in rest of the code 
    assert(x==7); 

    /* Rest of the code */

    return 0; 
} 


================================================
FILE: basic_content/assert/ignore_assert.c
================================================
/**
 * @file ignore_assert.c
 * @brief 忽略断言
 * @author 光城
 * @version v1
 * @date 2019-07-25
 */

# define NDEBUG // 忽略断言

#include<assert.h>

int main(){
    assert(x==5);
    return 0;
}


================================================
FILE: basic_content/bit/BUILD
================================================
# please run `bazel run basic_content/bit:bit`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "bit",
    srcs = ["bit.cpp"],
)

================================================
FILE: basic_content/bit/README.md
================================================
## 关于作者:

个人公众号:

![](../img/wechat.jpg)

## Bit field 是什么?

“ 位域 “ 或 “ 位段 “(Bit field)为一种数据结构,可以把数据以位的形式紧凑的储存,并允许程序员对此结构的位进行操作。这种数据结构的一个好处是它可以使数据单元节省储存空间,当程序需要成千上万个数据单元时,这种方法就显得尤为重要。第二个好处是位段可以很方便的访问一个整数值的部分内容从而可以简化程序源代码。而这种数据结构的缺点在于,位段实现依赖于具体的机器和系统,在不同的平台可能有不同的结果,这导致了位段在本质上是不可移植的。

- 位域在内存中的布局是与机器有关的
- 位域的类型必须是整型或枚举类型,带符号类型中的位域的行为将因具体实现而定
- 取地址运算符(&)不能作用于位域,任何指针都无法指向类的位域

## 位域使用

位域通常使用结构体声明, 该结构声明为每个位域成员设置名称,并决定其宽度:

```
struct bit_field_name
{
	type member_name : width;
};
```



| Elements       | Description                                                  |
| -------------- | ------------------------------------------------------------ |
| bit_field_name | 位域结构名                                                   |
| type           | 位域成员的类型,必须为 int、signed int 或者 unsigned int 类型 |
| member_name    | 位域成员名                                                   |
| width          | 规定成员所占的位数                                           |

例如声明如下一个位域:

```
struct _PRCODE
{
	unsigned int code1: 2;
	unsigned int cdde2: 2;
	unsigned int code3: 8;
};
struct _PRCODE prcode;
```

该定义使 `prcode`包含 2 个 2 Bits 位域和 1 个 8 Bits 位域,我们可以使用结构体的成员运算符对其进行赋值

```
prcode.code1 = 0;
prcode.code2 = 3;
procde.code3 = 102;
```


赋值时要注意值的大小不能超过位域成员的容量,例如 prcode.code3 为 8 Bits 的位域成员,其容量为 2^8 = 256,即赋值范围应为 [0,255]。

## 位域的大小和对齐

### 位域的大小

例如以下位域:

```
struct box 
{
	unsigned int a: 1;
	unsigned int  : 3;
	unsigned int b: 4;
};
```

该位域结构体中间有一个未命名的位域,占据 3 Bits,仅起填充作用,并无实际意义。 填充使得该结构总共使用了 8 Bits。但 C 语言使用 unsigned int 作为位域的基本单位,即使一个结构的唯一成员为 1 Bit 的位域,该结构大小也和一个 unsigned int 大小相同。 有些系统中,unsigned int 为 16 Bits,在 x86 系统中为 32 Bits。文章以下均默认 unsigned int 为 32 Bits。

### 位域的对齐

一个位域成员不允许跨越两个 unsigned int 的边界,如果成员声明的总位数超过了一个 unsigned int 的大小, 那么编辑器会自动移位位域成员,使其按照 unsigned int 的边界对齐。
例如:

```
struct stuff 
{
	unsigned int field1: 30;
	unsigned int field2: 4;
	unsigned int field3: 3;
};
```



`field1` + `field2` = 34 Bits,超出 32 Bits, 编译器会将`field2`移位至下一个 unsigned int 单元存放, stuff.field1 和 stuff.field2 之间会留下一个 2 Bits 的空隙, stuff.field3 紧跟在 stuff.field2 之后,该结构现在大小为 2 * 32 = 64 Bits。

这个空洞可以用之前提到的未命名的位域成员填充,我们也可以使用一个宽度为 0 的未命名位域成员令下一位域成员与下一个整数对齐。
例如:

```
struct stuff 
{
	unsigned int field1: 30;
	unsigned int       : 2;
	unsigned int field2: 4;
	unsigned int       : 0;
	unsigned int field3: 3; 
};
```



这里 stuff.field1 与 stuff.field2 之间有一个 2 Bits 的空隙,stuff.field3 则存储在下一个 unsigned int 中,该结构现在大小为 3 * 32 = 96 Bits。

学习代码见:[bit.cpp](bit.cpp)

## 位域的初始化和位的重映射

### 初始化

位域的初始化与普通结构体初始化的方法相同,这里列举两种,如下:

```
struct stuff s1= {20,8,6};
```

或者直接为位域成员赋值

```
struct stuff s1;
s1.field1 = 20;
s1.field2 = 8;
s1.field3 = 4;
```

### 位域的重映射 (Re-mapping)

声明一个 大小为 32 Bits 的位域

```
struct box {
	unsigned int ready:     2;
	unsigned int error:     2;
	unsigned int command:   4;
	unsigned int sector_no: 24;
}b1;
```

#### 利用重映射将位域归零

```
int* p = (int *) &b1;  // 将 "位域结构体的地址" 映射至 "整形(int*) 的地址" 
*p = 0;                // 清除 s1,将各成员归零
```

#### 利用联合 (union) 将 32 Bits 位域 重映射至 unsigned int 型

先简单介绍一下联合

> “联合” 是一种特殊的类,也是一种构造类型的数据结构。在一个 “联合” 内可以定义多种不同的数据类型, 一个被说明为该 “联合” 类型的变量中,允许装入该 “联合” 所定义的任何一种数据,这些数据共享同一段内存,以达到节省空间的目的
>
> “联合” 与 “结构” 有一些相似之处。但两者有本质上的不同。在结构中各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和(空结构除外,同时不考虑边界调整)。而在 “联合” 中,各成员共享一段内存空间, 一个联合变量的长度等于各成员中最长的长度。应该说明的是, 这里所谓的共享不是指把多个成员同时装入一个联合变量内, 而是指该联合变量可被赋予任一成员值,但每次只能赋一种值, 赋入新值则冲去旧值。

我们可以声明以下联合:

```
union u_box {
  struct box st_box;     
  unsigned int ui_box;
};
```



x86 系统中 unsigned int 和 box 都为 32 Bits, 通过该联合使 st_box 和 ui_box 共享一块内存。具体位域中哪一位与 unsigned int 哪一位相对应,取决于编译器和硬件。
利用联合将位域归零,代码如下:

```
union u_box u;
u.ui_box = 0;
```

> 学习参考自:<http://www.yuan-ji.me/C-C-%E4%BD%8D%E5%9F%9F-Bit-fields-%E5%AD%A6%E4%B9%A0%E5%BF%83%E5%BE%97/>

================================================
FILE: basic_content/bit/bit.cpp
================================================
#include <iostream>

using namespace std;
struct stuff {
  unsigned int field1 : 30;
  unsigned int : 2;
  unsigned int field2 : 4;
  unsigned int : 0;
  unsigned int field3 : 3;
};
int main() {
  struct stuff s = {1, 3, 5};
  cout << s.field1 << endl;
  cout << s.field2 << endl;
  cout << s.field3 << endl;
  cout << sizeof(s) << endl;
  return 0;
}


================================================
FILE: basic_content/c_poly/BUILD
================================================
# please run `bazel run basic_content/c_poly:c_examp`
# please run `bazel run basic_content/c_poly:c++_examp`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "c_examp",
    srcs = ["c_examp.c"],
)

cc_binary(
    name = "c++_examp",
    srcs = ["c++_examp.cpp"],
)

================================================
FILE: basic_content/c_poly/README.md
================================================
# C实现C++的面向对象特性

## 关于作者:

个人公众号:

![](../img/wechat.jpg)

## 1.C++实现案例

C++中的多态:在C++中会维护一张虚函数表,根据赋值兼容规则,我们知道父类的指针或者引用是可以指向子类对象的。

如果一个父类的指针或者引用调用父类的虚函数则该父类的指针会在自己的虚函数表中查找自己的函数地址,如果该父类对象的指针或者引用指向的是子类的对象,而且该子类已经重写了父类的虚函数,则该指针会调用子类的已经重写的虚函数。

学习案例代码见:[c++_examp.cpp](./c++_examp.cpp)



## 2.C实现

- 封装

C语言中是没有class类这个概念的,但是有struct结构体,我们可以考虑使用struct来模拟;

使用函数指针把属性与方法封装到结构体中。

- 继承

结构体嵌套

- 多态

类与子类方法的函数指针不同

在C语言的结构体内部是没有成员函数的,如果实现这个父结构体和子结构体共有的函数呢?我们可以考虑使用函数指针来模拟。但是这样处理存在一个缺陷就是:父子各自的函数指针之间指向的不是类似C++中维护的虚函数表而是一块物理内存,如果模拟的函数过多的话就会不容易维护了。

模拟多态,必须保持函数指针变量对齐(在内容上完全一致,而且变量对齐上也完全一致)。否则父类指针指向子类对象,运行崩溃!



学习案例代码见:[c_examp.c](./c_examp.c)


================================================
FILE: basic_content/c_poly/c++_examp.cpp
================================================
/**
 * @file c++_examp.cpp
 * @brief c++中的多态
 * @author 光城
 * @version v1
 * @date 2019-08-06
 */

#include <iostream>

using namespace std;
class A {
public:
  virtual void f() //虚函数实现
  {
    cout << "Base A::f() " << endl;
  }
};

class B : public A // 必须为共有继承,否则后面调用不到,class默认为私有继承!
{
public:
  virtual void f() //虚函数实现,子类中virtual关键字可以没有
  {
    cout << "Derived B::f() " << endl;
  }
};

int main() {
  A a; //基类对象
  B b; //派生类对象

  A *pa = &a; //父类指针指向父类对象
  pa->f();    //调用父类的函数

  pa = &b; //父类指针指向子类对象,多态实现
  pa->f(); //调用派生类同名函数
  return 0;
}


================================================
FILE: basic_content/c_poly/c_examp.c
================================================
/**
 * @file c_examp.c
 * @brief C实现多态
 * @author 光城
 * @version v1
 * @date 2019-08-06
 */

#include <stdio.h>

/// 重定义一个函数指针类型
typedef void (*pf) ();

/**
 * @brief 父类 
 */ 
typedef struct _A
{
    pf _f;
}A;


/**
 * @brief 子类
 */
typedef struct _B
{ 
    A _b; ///< 在子类中定义一个基类的对象即可实现对父类的继承。 
}B;

void FunA() 
{
    printf("%s\n","Base A::fun()");
}

void FunB() 
{
    printf("%s\n","Derived B::fun()");
}


int main() 
{
    A a;
    B b;

    a._f = FunA;
    b._b._f = FunB;

    A *pa = &a;
    pa->_f();
    pa = (A *)&b;   /// 让父类指针指向子类的对象,由于类型不匹配所以要进行强转 
    pa->_f();
    return 0;
}


================================================
FILE: basic_content/const/BUILD
================================================
# please run `bazel run basic_content/const:const_function`
# please run `bazel run basic_content/const:const_num`
load("@rules_cc//cc:defs.bzl", "cc_binary")

# Don't panic if you get compilation errors, this is what this code demonstrates, as expected.
cc_binary(
    name = "const_function",
    srcs = ["const_function.cpp"],
    copts = ["-std=c++11"]
)

# Don't panic if you get compilation errors, this is what this code demonstrates, as expected.
cc_binary(
    name = "const_num",
    srcs = ["const_num.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/const/README.md
================================================
## 关于作者

微信公众号:

![](../img/wechat.jpg)

## 1.const含义

常类型是指使用类型修饰符**const**说明的类型,常类型的变量或对象的值是不能被更新的。

## 2.const作用

+ 可以定义常量

```cpp
const int a=100;
```

+ 类型检查

    + const常量与`#define`宏定义常量的区别:
    > <strong><s>const常量具有类型,编译器可以进行安全检查;#define宏定义没有数据类型,只是简单的字符串替换,不能进行安全检查。</s></strong>感谢两位大佬指出这里问题,见:[issue](https://github.com/Light-City/CPlusPlusThings/issues/5)

    + const常量支持所有类型。
    + 其他情况下它只是一个 `const` 限定的变量,不要将与常量混淆。

+ 防止修改,起保护作用,增加程序健壮性

```cpp
void f(const int i){
    i++; // error!
}
```

+ 可以节省空间,避免不必要的内存分配

    + const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是像`#define`一样给出的是立即数。
    + const定义的常量在程序运行过程中只有一份拷贝,而`#define`定义的常量在内存中有若干个拷贝。

## 3.const对象默认为文件局部变量

<p><font style="color:red">注意:非const变量默认为extern。要使const变量能够在其他文件中访问,必须在文件中显式地指定它为extern。</font></p>

> 未被const修饰的变量在不同文件的访问

```cpp
// file1.cpp
int ext;
// file2.cpp
#include<iostream>

extern int ext;
int main(){
    std::cout<<(ext+10)<<std::endl;
}
```

> const常量在不同文件的访问

```cpp
// extern_file1.cpp
extern const int ext=12;
// extern_file2.cpp
#include<iostream>
extern const int ext;
int main(){
    std::cout<<ext<<std::endl;
}
```

> 小结:<br>可以发现未被const修饰的变量不需要extern显式声明!而const常量需要显式声明extern,并且需要做初始化!因为常量在定义后就不能被修改,所以定义时必须初始化。</font></p>

## 4.定义常量

```c++
const int b = 10;
b = 0; // error: assignment of read-only variable ‘b’
const string s = "helloworld";
const int i,j=0 // error: uninitialized const ‘i’
```

上述有两个错误:
+ b 为常量,不可更改!
+ i 为常量,必须进行初始化!(因为常量在定义后就不能被修改,所以定义时必须初始化。)

## 5.指针与const

与指针相关的const有四种:

```c++
const char * a; // 指向const对象的指针或者说指向常量的指针。
char const * a; // 同上
char * const a; // 指向类型对象的const指针。或者说常指针、const指针。
const char * const a; // 指向const对象的const指针。
```

> **小结:** <br>
> 如果*const*位于`*`的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;<br>如果const位于`*`的右侧,*const*就是修饰指针本身,即指针本身是常量。

**另一种解读方式**<br>
利用英文从右边往左边读,并且以to为分界,to之前为描述指针的特性,to之后为描述目标的特性<br>
```c++
const char * p; //p is a pointer to const char
char const * p; //同上
char * const p; //p is a const pointer to char
const char * const p; //p is a const pointer to const char
```
当指针被加上const特性,则指针不可改变指向的地址<br>
当指向的目标特性为char,则内容可以透过指针被修改,如: *char='y';<br>
当指向的目标特性为const char,则内容不可透过指针修改<br>

具体使用如下:

(1) **指向常量的指针**

```cpp
const int *ptr;
*ptr = 10; // error
```

ptr是一个指向int类型const对象的指针,const定义的是int类型,也就是ptr所指向的对象类型,而不是ptr本身,所以ptr可以不用赋初始值。但是不能通过ptr去修改所指对象的值。

除此之外,也不能使用void`*`指针保存const对象的地址,必须使用const void`*`类型的指针保存const对象的地址。

```c++
const int p = 10;
const void * vp = &p;
void *vp = &p; // error
```

另外一个重点是:**允许把非const对象的地址赋给指向const对象的指针**。

将非const对象的地址赋给const对象的指针:

```c++
const int *ptr;
int val = 3;
ptr = &val; // ok
```

我们不能通过ptr指针来修改val的值,即使它指向的是非const对象!

我们不能使用指向const对象的指针修改基础对象,然而如果该指针指向了非const对象,可用其他方式修改其所指的对象。可以修改const指针所指向的值的,但是不能通过const对象指针来进行而已!如下修改:

```c++
int *ptr1 = &val;
*ptr1=4;
cout<<*ptr<<endl;
```

> 小结:<br>1.对于指向常量的指针,不能通过指针来修改对象的值。<br>2.不能使用void`*`指针保存const对象的地址,必须使用const void`*`类型的指针保存const对象的地址。<br>3.允许把非const对象的地址赋值给const对象的指针,如果要修改指针所指向的对象值,必须通过其他方式修改,不能直接通过当前指针直接修改。

(2) **常指针**

const指针必须进行初始化,且const指针指向的值能修改,但指向不能修改。

```cpp
#include<iostream>
using namespace std;
int main(){
    int num=0, num1=1;
    int * const ptr=&num; // const指针必须初始化!且const指针的指向不能修改
    ptr = &num1; // error! const指针不能修改指向!
    cout<<*ptr<<endl;
}
```

代码出现编译错误:const指针不能修改指向。

```cpp
#include<iostream>
using namespace std;
int main(){
    int num=0, num1=1;
    int * const ptr=&num; // const指针必须初始化!且const指针的指向不能修改
    *ptr = 1;
    cout<<*ptr<<endl;
}
```

代码无事发生,正常输出1。

最后,当把一个const常量的地址赋值给ptr时候,由于ptr指向的是一个变量,而不是const常量,所以会报错,出现:const int`*` -> int `*`错误!

```cpp
#include<iostream>
using namespace std;
int main(){
    const int num=0;
    int * const ptr=&num; // error! const int* -> int*
    cout<<*ptr<<endl;
}
```

上述若改为 const int `*`ptr或者改为const int `*`const ptr,都可以正常!

(3)**指向常量的常指针**

理解完前两种情况,下面这个情况就比较好理解了:

```cpp
const int p = 3;
const int * const ptr = &p; 
```

ptr是一个const指针,然后指向了一个int 类型的const对象。

## 6.函数中使用const

> const修饰函数返回值

这个跟const修饰普通变量以及指针的含义基本相同:

(1)**const int**

```cpp
const int func1();
```

这个本身无意义,因为参数返回本身就是赋值给其他的变量!

(2)**const int***

```cpp
const int* func2();
```

指针指向的内容不变。

(3)int *const

```cpp
int *const func2();
```

指针本身不可变。

> const修饰函数参数

(1)传递过来的参数及指针本身在函数内不可变,无意义!

```cpp
void func(const int var); // 传递过来的参数不可变
void func(int *const var); // 指针本身不可变
```

表明参数在函数体内不能被修改,但此处没有任何意义,var本身就是形参,在函数内不会改变。包括传入的形参是指针也是一样。

输入参数采用“值传递”,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加const 修饰。

(2)**参数指针所指内容为常量不可变**

```cpp
void StringCopy(char *dst, const char *src);
```

其中src 是输入参数,dst 是输出参数。给src加上const修饰后,如果函数体内的语句试图改动src的内容,编译器将指出错误。这就是加了const的作用之一。

(3)**参数为引用,为了增加效率同时防止修改。**

```cpp
void func(const A &a)
```

对于非内部数据类型的参数而言,像void func(A a) 这样声明的函数注定效率比较低。因为函数体内将产生A 类型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程都将消耗时间。

为了提高效率,可以将函数声明改为void func(A &a),因为“引用传递”仅借用一下参数的别名而已,不需要产生临
时对象。

> 但是函数void func(A &a) 存在一个缺点:<br><br>“引用传递”有可能改变参数a,这是我们不期望的。解决这个问题很容易,加const修饰即可,因此函数最终成为
void func(const A &a)。

以此类推,是否应将void func(int x) 改写为void func(const int &x),以便提高效率?完全没有必要,因为内部数据类型的参数不存在构造、析构的过程,而复制也非常快,“值传递”和“引用传递”的效率几乎相当。

> 小结:<br>1.对于非内部数据类型的输入参数,应该将“值传递”的方式改为“const 引用传递”,目的是提高效率。例如将void func(A a) 改为void func(const A &a)。<br><br>2.对于内部数据类型的输入参数,不要将“值传递”的方式改为“const 引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。例如void func(int x) 不应该改为void func(const int &x)。</font></p>

以上解决了两个面试问题:

+ 如果函数需要传入一个指针,是否需要为该指针加上const,把const加在指针不同的位置有什么区别;
+ 如果写的函数需要传入的参数是一个复杂类型的实例,传入值参数或者引用参数有什么区别,什么时候需要为传入的引用参数加上const。 

## 7.类中使用const

在一个类中,任何不会修改数据成员的函数都应该声明为const类型。如果在编写const成员函数时,不慎修改 数据成员,或者调用了其它非const成员函数,编译器将指出错误,这无疑会提高程序的健壮性。

使用const关键字进行说明的成员函数,称为常成员函数。只有常成员函数才有资格操作常量或常对象,没有使用const关键字进行说明的成员函数不能用来操作常对象。

对于类中的const成员变量必须通过初始化列表进行初始化,如下所示:

```cpp
class Apple{
private:
    int people[100];
public:
    Apple(int i); 
    const int apple_number;
};

Apple::Apple(int i):apple_number(i)
{

}
```

const对象只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数.

例如:

```cpp
// apple.cpp
class Apple
{
private:
    int people[100];
public:
    Apple(int i); 
    const int apple_number;
    void take(int num) const;
    int add();
    int add(int num) const;
    int getCount() const;

};
// apple.cpp
Apple::Apple(int i) : apple_number(i)
{
}
int Apple::add(int num)
{
    take(num);
    return 0;
}
int Apple::add(int num) const
{
    take(num);
    return 0;
}
void Apple::take(int num) const
{
    std::cout << "take func " << num << std::endl;
}
int Apple::getCount() const
{
    take(1);
    //    add(); // error
    return apple_number;
}
int main()
{
    Apple a(2);
    cout << a.getCount() << endl;
    a.add(10);
    const Apple b(3);
    b.add(100);
    return 0;
}
// main.cpp
```
> 编译:bazel run basic_content/const/class_const/first_example:main<br>

此时报错,上面getCount()方法中调用了一个add方法,而add方法并非const修饰,所以运行报错。也就是说const成员函数只能访问const成员函数。

当调用改为:

```
const Apple b(3);
b.add(); // error
```
此时,可以证明的是const对象只能访问const成员函数。

我们除了上述的初始化const常量用初始化列表方式外,也可以通过下面方法:

第一:将常量定义与static结合,也就是:

```cpp
static const int apple_number
```

第二:在外面初始化:

```cpp
const int Apple::apple_number=10;
```

当然,如果你使用c++11进行编译,直接可以在定义出初始化,可以直接写成:

```cpp
static const int apple_number=10;
// 或者
const int apple_number=10;
```

这两种都在c++11中支持!

编译的时候加上`-std=c++11`即可!

这里提到了static,下面简单的说一下:

在C++中,static静态成员变量不能在类的内部初始化。在类的内部只是声明,定义必须在类定义体的外部,通常在类的实现文件中初始化。

在类中声明:

```cpp
static int ap;
```

在类实现文件中使用:

```cpp
int Apple::ap=666
```

对于此项,c++11不能进行声明并初始化,也就是上述使用方法。


================================================
FILE: basic_content/const/class_const/c++11_example/BUILD
================================================
# please run `bazel run basic_content/const/class_const/c++11_example:main`
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")

cc_library(
    name = "apple",
    srcs = ["apple.cpp"],
    hdrs = ["apple.h"],
)

cc_binary(
    name = "main",
    srcs = ["main.cpp"],
    deps = [
        ":apple",
    ],
)

================================================
FILE: basic_content/const/class_const/c++11_example/apple.cpp
================================================
#include "apple.h"
#include <iostream>

using namespace std;
Apple::Apple(int i) {}
int Apple::add(int num) {
  take(num);
  return 0;
}
int Apple::add(int num) const {
  take(num);
  return 0;
}
void Apple::take(int num) const { cout << "take func " << num << endl; }
int Apple::getCount() const {
  take(1);
  //    add(); //error
  return apple_number;
}

================================================
FILE: basic_content/const/class_const/c++11_example/apple.h
================================================
#pragma once

class Apple {
public:
  Apple(int i);
  // 使用c++11标准编译
  static const int apple_number = 10;
  // const int apple_number=10;
  void take(int num) const;
  int add(int num);
  int add(int num) const;
  int getCount() const;
};


================================================
FILE: basic_content/const/class_const/c++11_example/main.cpp
================================================
#include "apple.h"
#include <iostream>
using namespace std;
int main() {
  Apple a(2);
  cout << a.getCount() << endl;
  a.add(10);
  const Apple b(3);
  b.add(100);
  return 0;
}


================================================
FILE: basic_content/const/class_const/first_example/BUILD
================================================
# please run `bazel run basic_content/const/class_const/first_example:main`
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")

cc_library(
    name = "apple",
    srcs = ["apple.cpp"],
    hdrs = ["apple.h"],
)

cc_binary(
    name = "main",
    srcs = ["main.cpp"],
    deps = [
        ":apple",
    ],
)

================================================
FILE: basic_content/const/class_const/first_example/apple.cpp
================================================
#include "apple.h"
#include <iostream>

Apple::Apple(int i) : apple_number(i) {}
int Apple::add(int num) {
  take(num);
  return 0;
}
int Apple::add(int num) const {
  take(num);
  return 0;
}
void Apple::take(int num) const {
  std::cout << "take func " << num << std::endl;
}
int Apple::getCount() const {
  take(1);
  //    add(); //error
  return apple_number;
}

================================================
FILE: basic_content/const/class_const/first_example/apple.h
================================================
#pragma once

class Apple {
public:
  Apple(int i);
  const int apple_number;
  void take(int num) const;
  int add(int num);
  int add(int num) const;
  int getCount() const;
};


================================================
FILE: basic_content/const/class_const/first_example/main.cpp
================================================
#include "apple.h"
#include <iostream>
using namespace std;

int main() {
  Apple a(2);
  cout << a.getCount() << endl;
  a.add(10);
  const Apple b(3);
  b.add(100);
  return 0;
}


================================================
FILE: basic_content/const/class_const/overload_example/BUILD
================================================
# please run `bazel run basic_content/const/class_const/overload_example:main`
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")

cc_library(
    name = "apple",
    srcs = ["apple.cpp"],
    hdrs = ["apple.h"],
)

# Don't panic if you get compilation errors, this is what this code demonstrates, as expected.
cc_binary(
    name = "main",
    srcs = ["main.cpp"],
    deps = [
        ":apple",
    ],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/const/class_const/overload_example/apple.cpp
================================================
#include "apple.h"
#include <iostream>

int Apple::apple_number = 10;

Apple::Apple(int i) { apple_number = i; }
int Apple::add() {
  take(1);
  return 0;
}
int Apple::add(int num) const {
  take(num);
  return num;
}
void Apple::take(int num) const {
  std::cout << "take func " << num << std::endl;
}
int Apple::getCount() const {
  take(1);
  add(); // error
  return apple_number;
}

================================================
FILE: basic_content/const/class_const/overload_example/apple.h
================================================
#pragma once

class Apple {
public:
  Apple(int i);
  static int apple_number;
  void take(int num) const;
  int add();
  int add(int num) const;
  int getCount() const;
};


================================================
FILE: basic_content/const/class_const/overload_example/main.cpp
================================================
#include "apple.h"
#include <iostream>
using namespace std;

int main() {
  Apple a(2);
  cout << a.getCount() << endl;
  a.add(10);
  //     const Apple b(3);
  //     b.add(); // error
  return 0;
}


================================================
FILE: basic_content/const/class_const/static_example/BUILD
================================================
# please run `bazel run basic_content/const/class_const/static_example:main`
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")

cc_library(
    name = "apple",
    srcs = ["apple.cpp"],
    hdrs = ["apple.h"],
)

cc_binary(
    name = "main",
    srcs = ["main.cpp"],
    deps = [
        ":apple",
    ],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/const/class_const/static_example/apple.cpp
================================================
#include "apple.h"
#include <iostream>

const int Apple::apple_number = 10;
int Apple::ap = 666;
Apple::Apple(int i) {}
int Apple::add(int num) {
  take(num);
  return 0;
}
int Apple::add(int num) const {
  take(num);
  return 0;
}
void Apple::take(int num) const {
  std::cout << "take func " << num << std::endl;
}
int Apple::getCount() const {
  take(1);
  //    add(); //error
  return apple_number;
}

================================================
FILE: basic_content/const/class_const/static_example/apple.h
================================================
#pragma once
class Apple {
public:
  Apple(int i);
  static int ap; // 在类实现文件中定义并初始化
  static const int apple_number;
  void take(int num) const;
  int add(int num);
  int add(int num) const;
  int getCount() const;
};


================================================
FILE: basic_content/const/class_const/static_example/main.cpp
================================================
#include "apple.h"
#include <iostream>
int main() {
  Apple a(2);
  std::cout << a.getCount() << std::endl;
  std::cout << a.ap << std::endl;
  a.add(10);
  const Apple b(3);
  b.add(100);
  return 0;
}


================================================
FILE: basic_content/const/const_function.cpp
================================================
#include <iostream>
using namespace std;

void f(const int i) {
  i = 10; // error: assignment of read-only parameter ‘i’
  cout << i << endl;
}

int main() { f(1); }


================================================
FILE: basic_content/const/const_num.cpp
================================================
#include <iostream>
using namespace std;
int main() {
  const int b = 10;
  b = 0; // error
  const string s = "helloworld";
  const int i, j = 0;
}


================================================
FILE: basic_content/const/extern_const/BUILD
================================================
# please run `bazel run basic_content/const/extern_const:const_file1` and `# please run `bazel run basic_content/const/extern_const:file`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "const_file1",
    srcs = ["const_file1.cpp", "const_file2.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "file",
    srcs = ["file1.cpp", "file2.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/const/extern_const/const_file1.cpp
================================================
extern const int ext = 12;

================================================
FILE: basic_content/const/extern_const/const_file2.cpp
================================================
#include <iostream>
/**
 * by 光城
 * compile: g++ -o file const_file2.cpp const_file1.cpp
 * execute: ./file
 */
extern const int ext;
int main() { std::cout << ext << std::endl; }

================================================
FILE: basic_content/const/extern_const/file1.cpp
================================================
int ext;

================================================
FILE: basic_content/const/extern_const/file2.cpp
================================================
#include <iostream>
/**
 * by 光城
 * compile: g++ -o file file2.cpp file1.cpp
 * execute: ./file
 */
extern int ext;
int main() { std::cout << (ext + 10) << std::endl; }

================================================
FILE: basic_content/const/funciton_const/condition1/BUILD
================================================
# please run `bazel run basic_content/const/funciton_const/condition2:condition1`
# please run `bazel run basic_content/const/funciton_const/condition2:condition2`
# please run `bazel run basic_content/const/funciton_const/condition2:condition3`
load("@rules_cc//cc:defs.bzl", "cc_binary")

# Don't panic if you get compilation errors, this is what this code demonstrates, as expected.
cc_binary(
    name = "condition1",
    srcs = ["condition1.cpp"],
    copts = ["-std=c++11"]
)

# Don't panic if you get compilation errors, this is what this code demonstrates, as expected.
cc_binary(
    name = "condition2",
    srcs = ["condition2.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "condition3",
    srcs = ["condition3.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/const/funciton_const/condition1/condition1.cpp
================================================
#include <iostream>
using namespace std;

int main() {
  const int *ptr;
  *ptr = 10; // error
}


================================================
FILE: basic_content/const/funciton_const/condition1/condition2.cpp
================================================
#include <iostream>
using namespace std;

int main() {
  const int p = 10;
  // const void *vp = &p;  // const pointer to const data
  void *vp = (void*)&p; // ✅ C-style cast
}


================================================
FILE: basic_content/const/funciton_const/condition1/condition3.cpp
================================================
#include <iostream>
using namespace std;

int main() {
  const int *ptr;
  int val = 3;
  ptr = &val; // ok
  int *ptr1 = &val;
  *ptr1 = 4;
  cout << *ptr << endl;
}


================================================
FILE: basic_content/const/funciton_const/condition2/BUILD
================================================
# please run `bazel run basic_content/const/funciton_const/condition2:condition1`
# please run `bazel run basic_content/const/funciton_const/condition2:condition2`
# please run `bazel run basic_content/const/funciton_const/condition2:condition3`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "condition1",
    srcs = ["condition1.cpp"],
    copts = ["-std=c++11"]
)

# Don't panic if you get compilation errors, this is what this code demonstrates, as expected.
cc_binary(
    name = "condition2",
    srcs = ["condition2.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "condition3",
    srcs = ["condition3.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/const/funciton_const/condition2/condition1.cpp
================================================
#include <iostream>
using namespace std;
int main() {
  int num = 0;
  int *const ptr = &num; // const指针必须初始化!且const指针的指向不能修改
  int *t = &num;
  *t = 1;
  cout << *ptr << endl;
}


================================================
FILE: basic_content/const/funciton_const/condition2/condition2.cpp
================================================
#include <iostream>
using namespace std;
int main() {
  const int num = 0;
  int *const ptr = &num; // error! const int* -> int*
  cout << *ptr << endl;
}


================================================
FILE: basic_content/const/funciton_const/condition2/condition3.cpp
================================================
#include <iostream>
using namespace std;
int main() {
  const int num = 10;
  const int *const ptr = &num;
  cout << *ptr << endl;
}


================================================
FILE: basic_content/const/funciton_const/condition3/BUILD
================================================
# please run `bazel run basic_content/const/funciton_const/condition3:condition1`
load("@rules_cc//cc:defs.bzl", "cc_binary")

# Don't panic if you get compilation errors, this is what this code demonstrates, as expected.
cc_binary(
    name = "condition1",
    srcs = ["condition1.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/const/funciton_const/condition3/condition1.cpp
================================================
#include <iostream>
using namespace std;

int main() {
  const int p = 3;
  const int *const ptr = &p;
  cout << *ptr << endl;
}


================================================
FILE: basic_content/decltype/BUILD
================================================
# please run `bazel run basic_content/decltype:decltype`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "decltype",
    srcs = ["decltype.cpp"],
    copts = ["-std=c++11"]
)


================================================
FILE: basic_content/decltype/README.md
================================================
# decltype那些事

## 关于作者:

个人公众号:

![](../img/wechat.jpg)

## 1.基本使用
decltype的语法是:

```
decltype (expression)
```

这里的括号是必不可少的,decltype的作用是“查询表达式的类型”,因此,上面语句的效果是,返回 expression 表达式的类型。注意,decltype 仅仅“查询”表达式的类型,并不会对表达式进行“求值”。


### 1.1 推导出表达式类型

```
int i = 4;
decltype(i) a; //推导结果为int。a的类型为int。
```

### 1.2 与using/typedef合用,用于定义类型。

```c++
using size_t = decltype(sizeof(0));//sizeof(a)的返回值为size_t类型
using ptrdiff_t = decltype((int*)0 - (int*)0);
using nullptr_t = decltype(nullptr);
vector<int >vec;
typedef decltype(vec.begin()) vectype;
for (vectype i = vec.begin; i != vec.end(); i++)
{
//...
}
```

这样和auto一样,也提高了代码的可读性。

### 1.3 重用匿名类型

在C++中,我们有时候会遇上一些匿名类型,如:

```c++
struct 
{
    int d ;
    double b;
}anon_s;
```

而借助decltype,我们可以重新使用这个匿名的结构体:

```c++
decltype(anon_s) as ;//定义了一个上面匿名的结构体
```

### 1.4 泛型编程中结合auto,用于追踪函数的返回值类型

这也是decltype最大的用途了。

```c++
template <typename T>
auto multiply(T x, T y)->decltype(x*y)
{
	return x*y;
}
```

完整代码见:[decltype.cpp](decltype.cpp)

## 2.判别规则

对于decltype(e)而言,其判别结果受以下条件的影响:

如果e是一个没有带括号的标记符表达式或者类成员访问表达式,那么的decltype(e)就是e所命名的实体的类型。此外,如果e是一个被重载的函数,则会导致编译错误。
否则 ,假设e的类型是T,如果e是一个将亡值,那么decltype(e)为T&&
否则,假设e的类型是T,如果e是一个左值,那么decltype(e)为T&。
否则,假设e的类型是T,则decltype(e)为T。

标记符指的是除去关键字、字面量等编译器需要使用的标记之外的程序员自己定义的标记,而单个标记符对应的表达式即为标记符表达式。例如:
```c++
int arr[4]
```
则arr为一个标记符表达式,而arr[3]+0不是。

举例如下:

```c++
int i = 4;
int arr[5] = { 0 };
int *ptr = arr;
struct S{ double d; }s ;
void Overloaded(int);
void Overloaded(char);//重载的函数
int && RvalRef();
const bool Func(int);

//规则一:推导为其类型
decltype (arr) var1; //int[] 标记符表达式

decltype (ptr) var2;//int *  标记符表达式

decltype(s.d) var3;//doubel 成员访问表达式

//decltype(Overloaded) var4;//重载函数。编译错误。

//规则二:将亡值。推导为类型的右值引用。

decltype (RvalRef()) var5 = 1;

//规则三:左值,推导为类型的引用。

decltype ((i))var6 = i;     //int&

decltype (true ? i : i) var7 = i; //int&  条件表达式返回左值。

decltype (++i) var8 = i; //int&  ++i返回i的左值。

decltype(arr[5]) var9 = i;//int&. []操作返回左值

decltype(*ptr)var10 = i;//int& *操作返回左值

decltype("hello")var11 = "hello"; //const char(&)[9]  字符串字面常量为左值,且为const左值。


//规则四:以上都不是,则推导为本类型

decltype(1) var12;//const int

decltype(Func(1)) var13=true;//const bool

decltype(i++) var14 = i;//int i++返回右值
```

学习参考:https://www.cnblogs.com/QG-whz/p/4952980.html


================================================
FILE: basic_content/decltype/decltype.cpp
================================================
#include <iostream>
#include <vector>
using namespace std;
/**
 * 泛型编程中结合auto,用于追踪函数的返回值类型
 */
template <typename T>

auto multiply(T x, T y) -> decltype(x * y) {
  return x * y;
}

int main() {
  int nums[] = {1, 2, 3, 4};
  vector<int> vec(nums, nums + 4);
  vector<int>::iterator it;

  for (it = vec.begin(); it != vec.end(); it++)
    cout << *it << " ";
  cout << endl;

  using nullptr_t = decltype(nullptr);
  nullptr_t nu;
  int *p = NULL;
  if (p == nu)
    cout << "NULL" << endl;

  typedef decltype(vec.begin()) vectype;

  for (vectype i = vec.begin(); i != vec.end(); i++)
    cout << *i << " ";
  cout << endl;

  /**
   * 匿名结构体
   */
  struct {
    int d;
    double b;
  } anon_s;

  decltype(anon_s) as{1, 2.0}; // 定义了一个上面匿名的结构体

  cout << multiply(11, 2) << ":" << as.b << endl;

  return 0;
}


================================================
FILE: basic_content/enum/BUILD
================================================
# please run `bazel run basic_content/enum:classic_practice`
# please run `bazel run basic_content/enum:tradition_color`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "classic_practice",
    srcs = ["classic_practice.cpp"],
    copts = ["-std=c++11"]
)

# Don't panic if you get compilation errors, this is what this code demonstrates, as expected.
cc_binary(
    name = "tradition_color",
    srcs = ["tradition_color.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/enum/README.md
================================================
# 从初级到高级的enum那些事

## 关于作者:

个人公众号:

![](../img/wechat.jpg)


## 传统行为


枚举有如下问题:

- 作用域不受限,会容易引起命名冲突。例如下面无法编译通过的:

```c++
enum Color
{
    RED,
    BLUE
};
enum Feeling
{
    EXCITED,
    BLUE
};

int main()
{
    Color a = BLUE; // error
    Feeling b = EXCITED;
    std::cout << a << ":" << b << std::endl;
    return 0;
}
```
- 会隐式转换为int
- 用来表征枚举变量的实际类型不能明确指定,从而无法支持枚举类型的前向声明。

具体实现见:[tradition_color.cpp](tradition_color.cpp)

## 经典做法

解决作用域不受限带来的命名冲突问题的一个简单方法是,给枚举变量命名时加前缀,如上面例子改成 COLOR_BLUE 以及 FEELING_BLUE。

一般说来,为了一致性我们会把所有常量统一加上前缀。但是这样定义枚举变量的代码就显得累赘。C 程序中可能不得不这样做。不过 C++ 程序员恐怕都不喜欢这种方法。替代方案是命名空间:
```c++
namespace Color 
{
    enum Type
    {
        RED=15,
        YELLOW,
        BLUE
    };
};
```

这样之后就可以用 `Color::Type c = Color::RED;` 来定义新的枚举变量了。如果 `using namespace Color` 后,前缀还可以省去,使得代码简化。不过,因为命名空间是可以随后被扩充内容的,所以它提供的作用域封闭性不高。在大项目中,还是有可能不同人给不同的东西起同样的枚举类型名。

更“有效”的办法是用一个类或结构体来限定其作用域,例如:定义新变量的方法和上面命名空间的相同。不过这样就不用担心类在别处被修改内容。这里用结构体而非类,是因为本身希望这些常量可以公开访问。

```c++
struct Color1
{
    enum Type
    {
        RED=102,
        YELLOW,
        BLUE
    };
};
```

具体实现见:[classic_practice.cpp](classic_practice.cpp)

## C++11 的枚举类

上面的做法解决了第一个问题,但对于后两个仍无能为力。庆幸的是,C++11 标准中引入了“枚举类”(enum class),可以较好地解决上述问题。

- 新的enum的作用域不在是全局的
- 不能隐式转换成其他类型

```c++
/**
 * @brief C++11的枚举类
 * 下面等价于enum class Color2:int
 */
enum class Color2
{
    RED=2,
    YELLOW,
    BLUE
};
Color2 c2 = Color2::RED;
cout << static_cast<int>(c2) << endl; //必须转!
```

- 可以指定用特定的类型来存储enum

```c++
enum class Color3:char;  // 前向声明

// 定义
enum class Color3:char 
{
    RED='r',
    BLUE
};
char c3 = static_cast<char>(Color3::RED);
```

具体实现见:[classic_practice.cpp](classic_practice.cpp)

## 类中的枚举类型

有时我们希望某些常量只在类中有效。 由于#define 定义的宏常量是全局的,不能达到目的,于是想到使用const 修饰数据成员来实现。而const 数据成员的确是存在的,但其含义却不是我们所期望的。

const 数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的,因为类可以创建多个对象,不同的对象其 const 数据成员的值可以不同。 

不能在类声明中初始化 const 数据成员。以下用法是错误的,因为类的对象未被创建时,编译器不知道 SIZE 的值是什么。(c++11标准前)

```c++
class A 
{
  const int SIZE = 100;   // 错误,企图在类声明中初始化 const 数据成员 
  int array[SIZE];  // 错误,未知的 SIZE 
}; 
```

正确应该在类的构造函数的初始化列表中进行:

```c++
class A 
{
  A(int size);  // 构造函数 
  const int SIZE ;    
}; 
A::A(int size) : SIZE(size)  // 构造函数的定义
{ 

} 
A  a(100); // 对象 a 的 SIZE 值为 100 
A  b(200); // 对象 b 的 SIZE 值为 200 
```

怎样才能建立在整个类中都恒定的常量呢?

别指望 const 数据成员了,应该用类中的枚举常量来实现。例如:

```c++
class Person{
public:
    typedef enum {
        BOY = 0,
        GIRL
    }SexType;
};
//访问的时候通过,Person::BOY或者Person::GIRL来进行访问。
```

枚举常量不会占用对象的存储空间,它们在编译时被全部求值。

枚举常量的缺点是:它的隐含数据类型是整数,其最大值有限,且不能表示浮点。


================================================
FILE: basic_content/enum/classic_practice.cpp
================================================
#include <iostream>
using namespace std;
/**
 * @brief namespace解决作用域不受限
 */
namespace Color {
enum Type { RED = 15, YELLOW, BLUE };
};

/**
 * @brief 上述如果 using namespace Color 后,前缀还可以省去,使得代码简化。
 * 不过,因为命名空间是可以随后被扩充内容的,所以它提供的作用域封闭性不高。
 * 在大项目中,还是有可能不同人给不同的东西起同样的枚举类型名。
 * 更“有效”的办法是用一个类或结构体来限定其作用域。
 *
 * 定义新变量的方法和上面命名空间的相同。
 * 不过这样就不用担心类在别处被修改内容。
 * 这里用结构体而非类,一是因为本身希望这些常量可以公开访问,
 * 二是因为它只包含数据没有成员函数。
 */
struct Color1 {
  enum Type { RED = 102, YELLOW, BLUE };
};

/**
 * @brief C++11的枚举类
 * 下面等价于enum class Color2:int
 */
enum class Color2 { RED = 2, YELLOW, BLUE };

enum class Color3 : char; // 前向声明

// 定义
enum class Color3 : char { RED = 'r', BLUE };

int main() {
  // 定义新的枚举变量
  Color::Type c = Color::RED;
  cout << c << endl;
  /**
   * 上述的另一种方法:
   * using namespace Color; // 定义新的枚举变量
   * Type c = RED;
   */
  Color1 c1;
  cout << c1.RED << endl;

  Color1::Type c11 = Color1::BLUE;
  cout << c11 << endl;

  Color2 c2 = Color2::RED;
  cout << static_cast<int>(c2) << endl;

  char c3 = static_cast<char>(Color3::RED);
  cout << c3 << endl;
  return 0;
}


================================================
FILE: basic_content/enum/tradition_color.cpp
================================================
#include <iostream>
using namespace std;

enum Color { RED, BLUE };
enum Feeling { EXCITED, BLUE };

int main() {
  Color a = BLUE; // error
  Feeling b = EXCITED;
  std::cout << a << ":" << b << std::endl;
  return 0;
}


================================================
FILE: basic_content/explicit/BUILD
================================================
# please run `bazel run basic_content/explicit:explicit`
load("@rules_cc//cc:defs.bzl", "cc_binary")

# Don't panic if you get compilation errors, this is what this code demonstrates, as expected.
cc_binary(
    name = "explicit",
    srcs = ["explicit.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/explicit/README.md
================================================
# explicit(显式)关键字那些事

## 关于作者:

个人公众号:

![](../img/wechat.jpg)

- explicit 修饰构造函数时,可以防止隐式转换和复制初始化
- explicit 修饰转换函数时,可以防止隐式转换,但按语境转换除外


代码参见:[.explicit.cpp](./explicit.cpp)

参考链接:
> https://stackoverflow.com/questions/4600295/what-is-the-meaning-of-operator-bool-const


================================================
FILE: basic_content/explicit/explicit.cpp
================================================
#include <iostream>

using namespace std;

struct A {
  A(int) {}
  operator bool() const { return true; }
};

struct B {
  explicit B(int) {}
  explicit operator bool() const { return true; }
};

void doA(A a) {}

void doB(B b) {}

int main() {
  A a1(1);     // OK:直接初始化
  A a2 = 1;    // OK:复制初始化
  A a3{1};     // OK:直接列表初始化
  A a4 = {1};  // OK:复制列表初始化
  A a5 = (A)1; // OK:允许 static_cast 的显式转换
  doA(1);      // OK:允许从 int 到 A 的隐式转换
  if (a1)
    ; // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
  bool a6(a1); // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
  bool a7 = a1; // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
  bool a8 = static_cast<bool>(a1); // OK :static_cast 进行直接初始化

  B b1(1);     // OK:直接初始化
               //    B b2 = 1;        // 错误:被 explicit
               //    修饰构造函数的对象不可以复制初始化
  B b3{1};     // OK:直接列表初始化
               //    B b4 = { 1 };        // 错误:被 explicit
               //    修饰构造函数的对象不可以复制列表初始化
  B b5 = (B)1; // OK:允许 static_cast 的显式转换
               //    doB(1);            // 错误:被 explicit
               //    修饰构造函数的对象不可以从 int 到 B 的隐式转换
  if (b1)
    ; // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool
      // 的按语境转换
  bool b6(b1); // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B
               // 到 bool 的按语境转换
               //    bool b7 = b1;        // 错误:被 explicit 修饰转换函数
               //    B::operator bool() 的对象不可以隐式转换
  bool b8 = static_cast<bool>(b1); // OK:static_cast 进行直接初始化

  return 0;
}


================================================
FILE: basic_content/extern/README.md
================================================
# extern "C"

## 关于作者:

个人公众号:

![](../img/wechat.jpg)

## 1.C++与C编译区别

在C++中常在头文件见到extern "C"修饰函数,那有什么作用呢? 是用于C++链接在C语言模块中定义的函数。

C++虽然兼容C,但C++文件中函数编译后生成的符号与C语言生成的不同。因为C++支持函数重载,C++函数编译后生成的符号带有函数参数类型的信息,而C则没有。

例如`int add(int a, int b)`函数经过C++编译器生成.o文件后,`add`会变成形如`add_int_int`之类的, 而C的话则会是形如`_add`, 就是说:相同的函数,在C和C++中,编译后生成的符号不同。

这就导致一个问题:如果C++中使用C语言实现的函数,在编译链接的时候,会出错,提示找不到对应的符号。此时`extern "C"`就起作用了:告诉链接器去寻找`_add`这类的C语言符号,而不是经过C++修饰的符号。

## 2.C++调用C函数

C++调用C函数的例子: 引用C的头文件时,需要加`extern "C"`

```c++
//add.h
#ifndef ADD_H
#define ADD_H
int add(int x,int y);
#endif

//add.c
#include "add.h"

int add(int x,int y) {
    return x+y;
}

//add.cpp
#include <iostream>
#include "add.h"
using namespace std;
int main() {
    add(2,3);
    return 0;
}
```

编译:

```
//Generate add.o file
gcc -c add.c
```

链接:

```
g++ add.cpp add.o -o main
```

没有添加extern "C" 报错:

```c++
> g++ add.cpp add.o -o main                                   
add.o:在函数‘main’中:
add.cpp:(.text+0x0): `main'被多次定义
/tmp/ccH65yQF.o:add.cpp:(.text+0x0):第一次在此定义
/tmp/ccH65yQF.o:在函数‘main’中:
add.cpp:(.text+0xf):对‘add(int, int)’未定义的引用
add.o:在函数‘main’中:
add.cpp:(.text+0xf):对‘add(int, int)’未定义的引用
collect2: error: ld returned 1 exit status
```

添加extern "C"后:

`add.cpp`

```c++
#include <iostream>
using namespace std;
extern "C" {
    #include "add.h"
}
int main() {
    std::cout << add(2, 3) << std::endl;
    return 0;
}
```

编译的时候一定要注意,先通过gcc生成中间文件add.o。

```
gcc -c add.c 
```

然后编译:

```
g++ add.cpp add.o -o main
```

如果使用bazel编译,运行:`bazel run basic_content/extern/extern_c++:main`

而通常为了C代码能够通用,即既能被C调用,又能被C++调用,头文件通常会有如下写法:

```c
#ifdef __cplusplus
extern "C"{
#endif
int add(int x,int y);
#ifdef __cplusplus
}
#endif
```

即在C++调用该接口时,会以C接口的方式调用。这种方式使得C++者不需要额外的extern C,而标准库头文件通常也是类似的做法,否则你为何不需要extern C就可以直接使用stdio.h中的C函数呢?


上述案例源代码见:

- [add.h](extern_c++/add.h)

- [add.c](extern_c++/add.c)

- [add.cpp](extern_c++/add.cpp)

## 2.C中调用C++函数

`extern "C"`在C中是语法错误,需要放在C++头文件中。

```c
// add.h
#ifndef ADD_H
#define ADD_H
extern "C" {
    int add(int x,int y);
}
#endif

// add.cpp
#include "add.h"

int add(int x,int y) {
    return x+y;
}

// add.c
extern int add(int x,int y);
int main() {
    add(2,3);
    return 0;
}
```

编译:

```c
g++ -c add.cpp
```

链接:

```
gcc add.c add.o -o main
```

上述案例源代码见:

- [add.h](extern_c/add.h)

- [add.c](extern_c/add.c)

- [add.cpp](extern_c/add.cpp)

综上,总结出使用方法,在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误。所以使用extern "C"全部都放在于cpp程序相关文件或其头文件中。

总结出如下形式:

(1)C++调用C函数:

```c++
//xx.h
extern int add(...)

//xx.c
int add(){
    
}

//xx.cpp
extern "C" {
    #include "xx.h"
}
```

(2)C调用C++函数

```c
//xx.h
extern "C"{
    int add();
}
//xx.cpp
int add(){
    
}
//xx.c
extern int add();
```


不过与C++调用C接口不同,C++确实是能够调用编译好的C函数,而这里C调用C++,不过是把C++代码当成C代码编译后调用而已。也就是说,C并不能直接调用C++库函数。


================================================
FILE: basic_content/extern/extern_c/BUILD
================================================
# please run `bazel run basic_content/extern/extern_c:main`
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")

cc_library(
    name = "add",
    srcs = ["add.cpp"],
    hdrs = ["add.h"],
)

cc_binary(
    name = "main",
    srcs = ["add.c"],
    deps = [":add"],
)

================================================
FILE: basic_content/extern/extern_c/add.c
================================================
extern int add(int x,int y);
int main() {
    add(2,3);
    return 0;
}


================================================
FILE: basic_content/extern/extern_c/add.cpp
================================================
#include "add.h"

int add(int x, int y) { return x + y; }


================================================
FILE: basic_content/extern/extern_c/add.h
================================================
#ifndef ADD_H
#define ADD_H
extern "C" {
int add(int x, int y);
}
#endif


================================================
FILE: basic_content/extern/extern_c++/BUILD
================================================
# please run `bazel run basic_content/extern/extern_c++:main`
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")

cc_library(
    name = "add",
    srcs = ["add.c"],
    hdrs = ["add.h"],
)

cc_binary(
    name = "main",
    srcs = ["add.cpp"],
    deps = [":add"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/extern/extern_c++/add.c
================================================
#include "add.h"

int add(int x,int y) {
    return x+y;
}


================================================
FILE: basic_content/extern/extern_c++/add.cpp
================================================
#include <iostream>
using namespace std;
extern "C" {
#include "add.h"
}
int main() {
  std::cout << add(2, 3) << std::endl;
  return 0;
}


================================================
FILE: basic_content/extern/extern_c++/add.h
================================================
#ifndef ADD_H
#define ADD_H
extern int add(int x, int y);
#endif


================================================
FILE: basic_content/friend/BUILD
================================================
# please run `bazel run basic_content/friend:friend_class`
# please run `bazel run basic_content/friend:friend_func`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "friend_class",
    srcs = ["friend_class.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "friend_func",
    srcs = ["friend_func.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/friend/README.md
================================================
# 友元函数与友元类

## 关于作者:

个人公众号:

![](../img/wechat.jpg)

## 0.概述

友元提供了一种 普通函数或者类成员函数 访问另一个类中的私有或保护成员 的机制。也就是说有两种形式的友元:

(1)友元函数:普通函数对一个访问某个类中的私有或保护成员。

(2)友元类:类A中的成员函数访问类B中的私有或保护成员

优点:提高了程序的运行效率。

缺点:破坏了类的封装性和数据的透明性。

总结:
- 能访问私有成员
- 破坏封装性
- 友元关系不可传递
- 友元关系的单向性
- 友元声明的形式及数量不受限制

## 1.友元函数

在类声明的任何区域中声明,而定义则在类的外部。

```
friend <类型><友元函数名>(<参数表>);
```

注意,友元函数只是一个普通函数,并不是该类的类成员函数,它可以在任何地方调用,友元函数中通过对象名来访问该类的私有或保护成员。

具体代码见:[friend_func.cpp](friend_func.cpp)

```c++
#include <iostream>

using namespace std;

class A
{
public:
    A(int _a):a(_a){};
    friend int geta(A &ca);  ///< 友元函数
private:
    int a;
};

int geta(A &ca) 
{
    return ca.a;
}

int main()
{
    A a(3);    
    cout<<geta(a)<<endl;

    return 0;
}
```

## 2.友元类
友元类的声明在该类的声明中,而实现在该类外。

```
friend class <友元类名>;
```

类B是类A的友元,那么类B可以直接访问A的私有成员。

具体代码见:[friend_class.cpp](friend_class.cpp)
```c++
#include <iostream>

using namespace std;

class A
{
public:
    A(int _a):a(_a){};
    friend class B;
private:
    int a;
};

class B
{
public:
    int getb(A ca) {
        return  ca.a; 
    };
};

int main() 
{
    A a(3);
    B b;
    cout<<b.getb(a)<<endl;
    return 0;
}
```


## 3.注意
- 友元关系没有继承性
假如类B是类A的友元,类C继承于类A,那么友元类B是没办法直接访问类C的私有或保护成员。

- 友元关系没有传递性
假如类B是类A的友元,类C是类B的友元,那么友元类C是没办法直接访问类A的私有或保护成员,也就是不存在“友元的友元”这种关系。


================================================
FILE: basic_content/friend/friend_class.cpp
================================================
#include <iostream>

using namespace std;

class A {
public:
  A(int _a) : a(_a){};
  friend class B;

private:
  int a;
};

class B {
public:
  int getb(A ca) { return ca.a; };
};

int main() {
  A a(3);
  B b;
  cout << b.getb(a) << endl;
  return 0;
}


================================================
FILE: basic_content/friend/friend_func.cpp
================================================
#include <iostream>

using namespace std;

class A {
public:
  A(int _a) : a(_a){};
  friend int geta(A &ca); ///< 友元函数
private:
  int a;
};

int geta(A &ca) { return ca.a; }

int main() {
  A a(3);
  cout << geta(a) << endl;

  return 0;
}


================================================
FILE: basic_content/func_pointer/BUILD
================================================
# please run `bazel run basic_content/func_pointer:func_pointer`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "func_pointer",
    srcs = ["func_pointer.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/func_pointer/func_pointer.cpp
================================================
/**
 * @file func_pointer.cpp
 * @brief 函数指针的使用!
 * @author 光城
 * @version v1
 * @date 2019-07-20
 */

#include <iostream>
using namespace std;

/**
 * @brief
 * 定义了一个变量pFun,这个变量是个指针,指向返回值为空和参数为int的函数的指针!
 */
void (*pFun)(int);

/**
 * @brief 代表一种新类型,不是变量!所以与上述的pFun不一样!
 */
typedef void (*func)(void);

void myfunc(void) { cout << "asda" << endl; }

void glFun(int a) { cout << a << endl; }
int main() {
  func pfun = myfunc; /*赋值*/
  pfun();             /*调用*/
  pFun = glFun;
  (*pFun)(2);
}


================================================
FILE: basic_content/inline/BUILD
================================================
# please run `bazel run basic_content/inline:inline_virtual`
# please run `bazel run basic_content/inline:main`
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")

cc_library(
    name = "inline",
    hdrs = ["inline.h"],
)

cc_binary(
    name = "inline_virtual",
    srcs = ["inline_virtual.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "main",
    srcs = ["inline.cpp"],
    deps = [
        ":inline",
    ],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/inline/README.md
================================================
# inline那些事

## 关于作者:

个人公众号:

![](../img/wechat.jpg)

## 1.类中内联

头文件中声明方法

```c++

class A
{
public:
    void f1(int x); 

    /**
     * @brief 类中定义了的函数是隐式内联函数,声明要想成为内联函数,必须在实现处(定义处)加inline关键字。
     *
     * @param x
     * @param y
     */
    void Foo(int x,int y) ///< 定义即隐式内联函数!
    {
    
    };
    void f2(int x); ///< 声明后,要想成为内联函数,必须在定义处加inline关键字。  
};
```

实现文件中定义内联函数:

```c++
#include <iostream>
#include "inline.h"

using namespace std;

/**
 * @brief inline要起作用,inline要与函数定义放在一起,inline是一种“用于实现的关键字,而不是用于声明的关键字”
 *
 * @param x
 * @param y
 *
 * @return 
 */
int Foo(int x,int y);  // 函数声明
inline int Foo(int x,int y) // 函数定义
{
    return x+y;
}

// 定义处加inline关键字,推荐这种写法!
inline void A::f1(int x){

}

int main()
{

    
    cout<<Foo(1,2)<<endl;

}
/**
 * 编译器对 inline 函数的处理步骤
 * 将 inline 函数体复制到 inline 函数调用点处;
 * 为所用 inline 函数中的局部变量分配内存空间;
 * 将 inline 函数的的输入参数和返回值映射到调用方法的局部变量空间中;
 * 如果 inline 函数有多个返回点,将其转变为 inline 函数代码块末尾的分支(使用 GOTO)。
 */

```

内联能提高函数效率,但并不是所有的函数都定义成内联函数!内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。

- 如果执行函数体内代码的时间相比于函数调用的开销较大,那么效率的收获会更少!

- 另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。

以下情况不宜用内联:

(1)如果函数体内的代码比较长,使得内联将导致内存消耗代价比较高。

(2)如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。

## 2.虚函数(virtual)可以是内联函数(inline)吗?

- 虚函数可以是内联函数,内联是可以修饰虚函数的,但是当虚函数表现多态性的时候不能内联。
- 内联是在编译期建议编译器内联,而虚函数的多态性在运行期,编译器无法知道运行期调用哪个代码,因此虚函数表现为多态性时(运行期)不可以内联。
- `inline virtual` 唯一可以内联的时候是:编译器知道所调用的对象是哪个类(如 `Base::who()`),这只有在编译器具有实际对象而不是对象的指针或引用时才会发生。

```c++
#include <iostream>  
using namespace std;
class Base
{
public:
    inline virtual void who()
    {
        cout << "I am Base\n";
    }
    virtual ~Base() {}
};
class Derived : public Base
{
public:
    inline void who()  // 不写inline时隐式内联
    {
        cout << "I am Derived\n";
    }
};

int main()
{
    // 此处的虚函数 who(),是通过类(Base)的具体对象(b)来调用的,编译期间就能确定了,所以它可以是内联的,但最终是否内联取决于编译器。 
    Base b;
    b.who();

    // 此处的虚函数是通过指针调用的,呈现多态性,需要在运行时期间才能确定,所以不能为内联。  
    Base *ptr = new Derived();
    ptr->who();

    // 因为Base有虚析构函数(virtual ~Base() {}),所以 delete 时,会先调用派生类(Derived)析构函数,再调用基类(Base)析构函数,防止内存泄漏。
    delete ptr;
    ptr = nullptr;

    
    return 0;
} 
```





================================================
FILE: basic_content/inline/inline.cpp
================================================
#include "inline.h"
#include <iostream>

using namespace std;

/**
 * @brief
 * inline要起作用,inline要与函数定义放在一起,inline是一种“用于实现的关键字,而不是用于声明的关键字”
 *
 * @param x
 * @param y
 *
 * @return
 */
int Foo(int x, int y);       // 函数声明
inline int Foo(int x, int y) // 函数定义
{
  return x + y;
}

// 定义处加inline关键字,推荐这种写法!
inline void A::f1(int x) {}

/**
 * @brief
 * 内联能提高函数效率,但并不是所有的函数都定义成内联函数!内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。
 * 如果执行函数体内代码的时间相比于函数调用的开销较大,那么效率的收货会更少!另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。
 * 以下情况不宜用内联:
 *  (1) 如果函数体内的代码比较长,使得内联将导致内存消耗代价比较高。
 *   (2)  如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。
 *
 * @return
 */
int main() { cout << Foo(1, 2) << endl; }
/**
 * 编译器对 inline 函数的处理步骤
 * 将 inline 函数体复制到 inline 函数调用点处;
 * 为所用 inline 函数中的局部变量分配内存空间;
 * 将 inline 函数的的输入参数和返回值映射到调用方法的局部变量空间中;
 * 如果 inline 函数有多个返回点,将其转变为 inline 函数代码块末尾的分支(使用
 * GOTO)。
 */


================================================
FILE: basic_content/inline/inline.h
================================================
#pragma once
class A {
public:
  void f1(int x);

  /**
   * @brief
   * 类中定义了的函数是隐式内联函数,声明要想成为内联函数,必须在实现处(定义处)加inline关键字。
   *
   * @param x
   * @param y
   */
  void Foo(int x, int y) ///< 定义即隐式内联函数!
      {

      };
  void f2(int x); ///< 声明后,要想成为内联函数,必须在定义处加inline关键字。
};


================================================
FILE: basic_content/inline/inline_virtual.cpp
================================================
#include <iostream>
using namespace std;
class Base {
public:
  inline virtual void who() { cout << "I am Base\n"; }
  virtual ~Base() {}
};
class Derived : public Base {
public:
  inline void who() // 不写inline时隐式内联
  {
    cout << "I am Derived\n";
  }
};

int main() {
  // 此处的虚函数
  // who(),是通过类(Base)的具体对象(b)来调用的,编译期间就能确定了,所以它可以是内联的,但最终是否内联取决于编译器。
  Base b;
  b.who();

  // 此处的虚函数是通过指针调用的,呈现多态性,需要在运行时期间才能确定,所以不能为内联。
  Base *ptr = new Derived();
  ptr->who();

  // 因为Base有虚析构函数(virtual ~Base() {}),所以 delete
  // 时,会先调用派生类(Derived)析构函数,再调用基类(Base)析构函数,防止内存泄漏。
  delete ptr;

  return 0;
}


================================================
FILE: basic_content/macro/BUILD
================================================
# please run `bazel run basic_content/macro:do_while`
# please run `bazel run basic_content/sig_examp:sig_examp`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "do_while",
    srcs = ["do_while.cpp"],
    copts = ["-std=c++11"],
)

cc_binary(
    name = "sig_examp",
    srcs = ["sig_examp.cpp"],
    copts = ["-std=c++11"],
)


================================================
FILE: basic_content/macro/README.md
================================================
# 宏那些事

## 关于作者:

个人公众号:

![](../img/wechat.jpg)

## 1.宏中包含特殊符号

分为几种:`#`,`##`,`\`

### 1.1 字符串化操作符(#)

**在一个宏中的参数前面使用一个#,预处理器会把这个参数转换为一个字符数组**,换言之就是:**#是“字符串化”的意思,出现在宏定义中的#是把跟在后面的参数转换成一个字符串**。

**注意:其只能用于有传入参数的宏定义中,且必须置于宏定义体中的参数名前。**

例如:

```c++
#define exp(s) printf("test s is:%s\n",s)
#define exp1(s) printf("test s is:%s\n",#s)
#define exp2(s) #s 
int main() {
    exp("hello");
    exp1(hello);

    string str = exp2(   bac );
    cout<<str<<" "<<str.size()<<endl;
    /**
     * 忽略传入参数名前面和后面的空格。
     */
    string str1 = exp2( asda  bac );
    /**
     * 当传入参数名间存在空格时,编译器将会自动连接各个子字符串,
     * 用每个子字符串之间以一个空格连接,忽略剩余空格。
     */
    cout<<str1<<" "<<str1.size()<<endl;
    return 0;
}
```

上述代码给出了基本的使用与空格处理规则,空格处理规则如下:

- 忽略传入参数名前面和后面的空格。

```c++
string str = exp2(   bac );
cout<<str<<" "<<str.size()<<endl;
```

输出:

```
bac 3
```

- 当传入参数名间存在空格时,编译器将会自动连接各个子字符串,用每个子字符串之间以一个空格连接,忽略剩余空格。

```c++
string str1 = exp2( asda  bac );
cout<<str1<<" "<<str1.size()<<endl;
```

输出:

```
asda bac 8
```

### 1.2 符号连接操作符(##)

**“##”是一种分隔连接方式,它的作用是先分隔,然后进行强制连接。将宏定义的多个形参转换成一个实际参数名。**

注意事项:

**(1)当用##连接形参时,##前后的空格可有可无。**

**(2)连接后的实际参数名,必须为实际存在的参数名或是编译器已知的宏定义。**

**(3)如果##后的参数本身也是一个宏的话,##会阻止这个宏的展开。**

示例:

```c++

#define expA(s) printf("前缀加上后的字符串为:%s\n",gc_##s)  //gc_s必须存在
// 注意事项2
#define expB(s) printf("前缀加上后的字符串为:%s\n",gc_  ##  s)  //gc_s必须存在
// 注意事项1
#define gc_hello1 "I am gc_hello1"
int main() {
    // 注意事项1
    const char * gc_hello = "I am gc_hello";
    expA(hello);
    expB(hello1);
}
```

### 1.3 续行操作符(\) 

**当定义的宏不能用一行表达完整时,可以用”\”表示下一行继续此宏的定义。**

**注意 \ 前留空格。**

```c++
#define MAX(a,b) ((a)>(b) ? (a) \
   :(b))  
int main() {
    int max_val = MAX(3,6);
    cout<<max_val<<endl;
}
```

上述代码见:[sig_examp.cpp](sig_examp.cpp)

## 2.do{...}while(0)的使用

### 2.1 避免语义曲解

例如:

```
#define fun() f1();f2();
if(a>0)
	fun()
```

这个宏被展开后就是:

```
if(a>0)
	f1();
	f2();
```

本意是a>0执行f1 f2,而实际是f2每次都会执行,所以就错误了。

为了解决这种问题,在写代码的时候,通常可以采用`{}`块。

如:

```c++
#define fun() {f1();f2();}
if(a>0)
	fun();
// 宏展开
if(a>0)
{
    f1();
    f2();
};
```

但是会发现上述宏展开后多了一个分号,实际语法不太对。(虽然编译运行没问题,正常没分号)。

### 2.2避免使用goto控制流

在一些函数中,我们可能需要在return语句之前做一些清理工作,比如释放在函数开始处由malloc申请的内存空间,使用goto总是一种简单的方法:

```c++
int f() {
    int *p = (int *)malloc(sizeof(int));
    *p = 10; 
    cout<<*p<<endl;
#ifndef DEBUG
    int error=1;
#endif
    if(error)
        goto END;
    // dosomething
END:
    cout<<"free"<<endl;
    free(p);
    return 0;
}
```

但由于goto不符合软件工程的结构化,而且有可能使得代码难懂,所以很多人都不倡导使用,这个时候我们可以使用do{...}while(0)来做同样的事情:

```c++
int ff() {
    int *p = (int *)malloc(sizeof(int));
    *p = 10; 
    cout<<*p<<endl;
    do{ 
#ifndef DEBUG
        int error=1;
#endif
        if(error)
            break;
        //dosomething
    }while(0);
    cout<<"free"<<endl;
    free(p);
    return 0;
}
```

这里将函数主体部分使用do{...}while(0)包含起来,使用break来代替goto,后续的清理工作在while之后,现在既能达到同样的效果,而且代码的可读性、可维护性都要比上面的goto代码好的多了。

### 2.3 避免由宏引起的警告

内核中由于不同架构的限制,很多时候会用到空宏,。在编译的时候,这些空宏会给出warning,为了避免这样的warning,我们可以使用do{...}while(0)来定义空宏:

```
#define EMPTYMICRO do{}while(0)
```

### 2.4 **定义单一的函数块来完成复杂的操作**

如果你有一个复杂的函数,变量很多,而且你不想要增加新的函数,可以使用do{...}while(0),将你的代码写在里面,里面可以定义变量而不用考虑变量名会同函数之前或者之后的重复。
这种情况应该是指一个变量多处使用(但每处的意义还不同),我们可以在每个do-while中缩小作用域,比如:

```c++
int fc()
{
    int k1 = 10;
    cout<<k1<<endl;
    do{
        int k1 = 100;
        cout<<k1<<endl;
    }while(0);
    cout<<k1<<endl;
}
```

上述代码见:[do_while.cpp](do_while.cpp)

学习文章:<https://www.cnblogs.com/lizhenghn/p/3674430.html>



================================================
FILE: basic_content/macro/do_while.cpp
================================================
#include <iostream>
#include <malloc.h>

using namespace std;
#define f1() cout << "f1()" << endl;
#define f2() cout << "f2()" << endl;

#define fun()                                                                  \
  {                                                                            \
    f1();                                                                      \
    f2();                                                                      \
  }
#define fun1()                                                                 \
  do {                                                                         \
    f1();                                                                      \
    f2();                                                                      \
  } while (0)

int f() {
  int *p = (int *)malloc(sizeof(int));
  *p = 10;
  cout << *p << endl;
#ifndef DEBUG
  int error = 1;
#endif
  if (error)
    goto END;

  // dosomething
END:
  cout << "free" << endl;
  free(p);
  return 0;
}

int ff() {

  int *p = (int *)malloc(sizeof(int));
  *p = 10;
  cout << *p << endl;

  do {
#ifndef DEBUG
    int error = 1;
#endif
    if (error)
      break;
    // dosomething
  } while (0);

  cout << "free" << endl;
  free(p);
  return 0;
}

int fc() {
  int k1 = 10;
  cout << k1 << endl;
  do {
    int k1 = 100;
    cout << k1 << endl;
  } while (0);
  cout << k1 << endl;
  return 0;
}

int main() {

  if (1 > 0)
    fun();

  if (2 > 0)
    fun1();

  f();
  ff();
  fc();
  return 0;
}


================================================
FILE: basic_content/macro/sig_examp.cpp
================================================
#include <cstring>
#include <iostream>
#include <stdio.h>
#include <string>

using namespace std;

///===========================================
/**
 * (#)字符串操作符
 */
///===========================================
#define exp(s) printf("test s is:%s\n", s)
#define exp1(s) printf("test s is:%s\n", #s)

#define exp2(s) #s

///===========================================
/**
 *(##)符号连接操作符
 */
///===========================================
#define expA(s) printf("前缀加上后的字符串为:%s\n", gc_##s) // gc_s必须存在

#define expB(s) printf("前缀加上后的字符串为:%s\n", gc_##s) // gc_s必须存在

#define gc_hello1 "I am gc_hello1"

///===========================================
/**
 * (\)续行操作符
 */
///===========================================
#define MAX(a, b) ((a) > (b) ? (a) : (b))

int main() {
  ///===========================================
  /**
   * (#)字符串操作符
   */
  ///===========================================
  exp("hello");
  exp1(hello);

  string str = exp2(bac);
  cout << str << " " << str.size() << endl;
  /**
   * 忽略传入参数名前面和后面的空格。
   */
  string str1 = exp2(asda bac);
  /**
   * 当传入参数名间存在空格时,编译器将会自动连接各个子字符串,
   * 用每个子字符串之间以一个空格连接,忽略剩余空格。
   */
  cout << str1 << " " << str1.size() << endl;

  ///===========================================
  /**
   * (#)字符串操作符
   */
  ///===========================================

  const char *gc_hello = "I am gc_hello";
  expA(hello);
  expB(hello1);

  char var1_p[20];
  char var2_p[20];

  // 连接后的实际参数名赋值
  strcpy(var1_p, "aaaa");
  strcpy(var2_p, "bbbb");

  ///===========================================
  /**
   * (\)续行操作符
   */
  ///===========================================
  int max_val = MAX(3, 6);
  cout << max_val << endl;
  return 0;
}


================================================
FILE: basic_content/maohao/BUILD
================================================
# please run `bazel run basic_content/maohao:maohao`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "maohao",
    srcs = ["maohao.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/maohao/README.md
================================================
# :: 范围解析运算符那些事

## 关于作者:

个人公众号:

![](../img/wechat.jpg)

- 全局作用域符(::name):用于类型名称(类、类成员、成员函数、变量等)前,表示作用域为全局命名空间
- 类作用域符(class::name):用于表示指定类型的作用域范围是具体某个类的
- 命名空间作用域符(namespace::name):用于表示指定类型的作用域范围是具体某个命名空间的

具体代码见:[maohao.cpp](maohao.cpp)



================================================
FILE: basic_content/maohao/maohao.cpp
================================================
#include <iostream>
using namespace std;

int count = 0; // 全局(::)的count

class A {
public:
  static int count; // 类A的count (A::count)
};
// 静态变量必须在此处定义
int A::count;
int main() {
  ::count = 1;  // 设置全局的count为1
  A::count = 5; // 设置类A的count为2
  cout << A::count << endl;
  //    int count=3; // 局部count
  //    count=4;     // 设置局部的count为4
  return 0;
}


================================================
FILE: basic_content/pointer_refer/BUILD
================================================
# please run `bazel run basic_content/pointer_refer:copy_construct`
# please run `bazel run basic_content/pointer_refer:effec`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "copy_construct",
    srcs = ["copy_construct.cpp"],
    copts = ["-std=c++11", "-fno-elide-constructors"]
)

cc_binary(
    name = "effec",
    srcs = ["effec.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/pointer_refer/README.md
================================================
# 引用与指针那些事

## 关于作者:

个人公众号:

![](../img/wechat.jpg)

## 1.引用与指针

总论:

| 引用         | 指针         |
| ------------ | ------------ |
| 必须初始化   | 可以不初始化 |
| 不能为空     | 可以为空     |
| 不能更换目标 | 可以更换目标 |

> 引用必须初始化,而指针可以不初始化。

我们在定义一个引用的时候必须为其指定一个初始值,但是指针却不需要。

```c++
int &r;    //不合法,没有初始化引用
int *p;    //合法,但p为野指针,使用需要小心
```

> 引用不能为空,而指针可以为空。

由于引用不能为空,所以我们在使用引用的时候不需要测试其合法性,而在使用指针的时候需要首先判断指针是否为空指针,否则可能会引起程序崩溃。

```c++
void test_p(int* p)
{
  	if(p != null_ptr)    //对p所指对象赋值时需先判断p是否为空指针
    	*p = 3;
    return;
}
void test_r(int& r)
{
    r = 3;    //由于引用不能为空,所以此处无需判断r的有效性就可以对r直接赋值
    return;
}
```

> 引用不能更换目标

指针可以随时改变指向,但是引用只能指向初始化时指向的对象,无法改变。

```
int a = 1;
int b = 2;

int &r = a;    //初始化引用r指向变量a
int *p = &a;   //初始化指针p指向变量a

p = &b;        //指针p指向了变量b
r = b;         //引用r依然指向a,但a的值变成了b
```

## 2.引用

#### 左值引用

常规引用,一般表示对象的身份。

#### 右值引用

右值引用就是必须绑定到右值(一个临时对象、将要销毁的对象)的引用,一般表示对象的值。

右值引用可实现转移语义(Move Sementics)和精确传递(Perfect Forwarding),它的主要目的有两个方面:

- 消除两个对象交互时不必要的对象拷贝,节省运算存储资源,提高效率。
- 能够更简洁明确地定义泛型函数。

#### 引用折叠

- `X& &`、`X& &&`、`X&& &` 可折叠成 `X&`
- `X&& &&` 可折叠成 `X&&`

C++的引用**在减少了程序员自由度的同时提升了内存操作的安全性和语义的优美性**。比如引用强制要求必须初始化,可以让我们在使用引用的时候不用再去判断引用是否为空,让代码更加简洁优美,避免了指针满天飞的情形。除了这种场景之外引用还用于如下两个场景:

> 引用型参数

一般我们使用const reference参数作为只读形参,这种情况下既可以避免参数拷贝还可以获得与传值参数一样的调用方式。

```c++
void test(const vector<int> &data)
{
    //...
}
int main()
{
  	vector<int> data{1,2,3,4,5,6,7,8};
    test(data);
}
```

> 引用型返回值

C++提供了重载运算符的功能,我们在重载某些操作符的时候,使用引用型返回值可以获得跟该操作符原来语法相同的调用方式,保持了操作符语义的一致性。一个例子就是operator []操作符,这个操作符一般需要返回一个引用对象,才能正确的被修改。

```c++
vector<int> v(10);
v[5] = 10;    //[]操作符返回引用,然后vector对应元素才能被修改
              //如果[]操作符不返回引用而是指针的话,赋值语句则需要这样写
*v[5] = 10;   //这种书写方式,完全不符合我们对[]调用的认知,容易产生误解
```

## 3.指针与引用的性能差距

指针与引用之间有没有性能差距呢?这种问题就需要进入汇编层面去看一下。我们先写一个test1函数,参数传递使用指针:

```c++
void test1(int* p)
{
    *p = 3;    //此处应该首先判断p是否为空,为了测试的需要,此处我们没加。
    return;
}
```

该代码段对应的汇编代码如下:

```c++
(gdb) disassemble 
Dump of assembler code for function test1(int*):
   0x0000000000400886 <+0>:  push   %rbp
   0x0000000000400887 <+1>:  mov    %rsp,%rbp
   0x000000000040088a <+4>:  mov    %rdi,-0x8(%rbp)
=> 0x000000000040088e <+8>:  mov    -0x8(%rbp),%rax
   0x0000000000400892 <+12>: movl   $0x3,(%rax)
   0x0000000000400898 <+18>: nop
   0x0000000000400899 <+19>: pop    %rbp
   0x000000000040089a <+20>: retq   
End of assembler dump.

```

上述代码1、2行是参数调用保存现场操作;第3行是参数传递,函数调用第一个参数一般放在rdi寄存器,此行代码把rdi寄存器值(指针p的值)写入栈中;第4行是把栈中p的值写入rax寄存器;第5行是把立即数3写入到**rax寄存器值所指向的内存**中,此处要注意(%rax)两边的括号,这个括号并并不是可有可无的,(%rax)和%rax完全是两种意义,(%rax)代表rax寄存器中值所代表地址部分的内存,即相当于C++代码中的*p,而%rax代表rax寄存器,相当于C++代码中的p值,所以汇编这里使用了(%rax)而不是%rax。

我们再写出参数传递使用引用的C++代码段test2:

```c++
void test2(int& r)
{
    r = 3;    //赋值前无需判断reference是否为空
    return;
}
```

这段代码对应的汇编代码如下:

```c++
(gdb) disassemble 
Dump of assembler code for function test2(int&):
   0x000000000040089b <+0>:  push   %rbp
   0x000000000040089c <+1>:  mov    %rsp,%rbp
   0x000000000040089f <+4>:  mov    %rdi,-0x8(%rbp)
=> 0x00000000004008a3 <+8>:  mov    -0x8(%rbp),%rax
   0x00000000004008a7 <+12>: movl   $0x3,(%rax)
   0x00000000004008ad <+18>: nop
   0x00000000004008ae <+19>: pop    %rbp
   0x00000000004008af <+20>: retq   
End of assembler dump.

```

我们发现test2对应的汇编代码和test1对应的汇编代码完全相同,这说明C++编译器在编译程序的时候将指针和引用编译成了完全一样的机器码。所以C++中的引用只是C++对指针操作的一个“语法糖”,在底层实现时C++编译器实现这两种操作的方法完全相同。

## 3.总结

C++中引入了引用操作,在对引用的使用加了更多限制条件的情况下,保证了引用使用的安全性和便捷性,还可以保持代码的优雅性。在适合的情况使用适合的操作,引用的使用可以一定程度避免“指针满天飞”的情况,对于提升程序稳定性也有一定的积极意义。最后,指针与引用底层实现都是一样的,不用担心两者的性能差距。

上述部分参考自:<http://irootlee.com/juicer_pointer_reference/#>


================================================
FILE: basic_content/pointer_refer/copy_construct.cpp
================================================
/**
 * @file copy_construct.cpp
 * @brief g++ -o copy_construct copy_construct.cpp -fno-elide-constructors
 * -fno-elide-constructors选项(关闭返回值优化)
 * @author 光城
 * @version v1
 * @date 2019-08-09
 */

#include <iostream>
using namespace std;

class Copyable {
public:
  Copyable() {}
  Copyable(const Copyable &o) { cout << "Copied" << endl; }
};
Copyable ReturnRvalue() {
  return Copyable(); // 返回一个临时对象
}
void AcceptVal(Copyable a) {}
void AcceptRef(const Copyable &a) {}

int main() {
  cout << "pass by value: " << endl;
  AcceptVal(ReturnRvalue()); // 应该调用两次拷贝构造函数
  cout << "pass by reference: " << endl;
  AcceptRef(ReturnRvalue()); // 应该只调用一次拷贝构造函数
}


================================================
FILE: basic_content/pointer_refer/effec.cpp
================================================
#include <iostream>
using namespace std;
void test1(int *p) {
  *p = 3; //此处应该首先判断p是否为空,为了测试的需要,此处我们没加。
  return;
}

void test2(int &p) {
  p = 3; //此处应该首先判断p是否为空,为了测试的需要,此处我们没加。
  return;
}

int main() {
  int a = 10;
  int *p = &a;
  test1(p);
  test2(a);
  cout << a << endl;
  return 0;
}


================================================
FILE: basic_content/sizeof/BUILD
================================================
# please run `bazel run basic_content/sizeof:blackclass`
# please run `bazel run basic_content/sizeof:genA`
# please run `bazel run basic_content/sizeof:geninhe`
# please run `bazel run basic_content/sizeof:moreinhe`
# please run `bazel run basic_content/sizeof:morevir`
# please run `bazel run basic_content/sizeof:static`
# please run `bazel run basic_content/sizeof:virinhe`
# please run `bazel run basic_content/sizeof:virmoreinhe`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "blackclass",
    srcs = ["blackclass.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "genA",
    srcs = ["genA.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "geninhe",
    srcs = ["geninhe.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "moreinhe",
    srcs = ["moreinhe.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "static",
    srcs = ["static.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "virinhe",
    srcs = ["virinhe.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "virmoreinhe",
    srcs = ["virmoreinhe.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/sizeof/README.md
================================================
# 类大小计算

首先来个总结,然后下面给出实际例子,实战!

- 空类的大小为1字节
- 一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间。
- 对于包含虚函数的类,不管有多少个虚函数,只有一个虚指针,vptr的大小。
- 普通继承,派生类继承了所有基类的函数与成员,要按照字节对齐来计算大小
- 虚函数继承,不管是单继承还是多继承,都是继承了基类的vptr。(32位操作系统4字节,64位操作系统 8字节)!
- 虚继承,继承基类的vptr。

## 1.原则1

```c++
/**
 * @file blackclass.cpp
 * @brief 空类的大小为1字节
 * @author 光城
 * @version v1
 * @date 2019-07-21
 */
#include<iostream>
using namespace std;
class A{};
int main()
{
    cout<<sizeof(A)<<endl;
    return 0;
}
```

## 2.原则2

```c++
/**
 * @file static.cpp
 * @brief 静态数据成员
 * 静态数据成员被编译器放在程序的一个global data members中,它是类的一个数据成员,但不影响类的大小。不管这个类产生了多少个实例,还是派生了多少新的类,静态数据成员只有一个实例。静态数据成员,一旦被声明,就已经存在。 
 * @author 光城
 * @version v1
 * @date 2019-07-21
 */
#include<iostream>
using namespace std;
class A
{
    public:
        char b;
        virtual void fun() {};
        static int c;
        static int d;
        static int f;
};

int main()
{
    /**
     * @brief 16  字节对齐、静态变量不影响类的大小、vptr指针=8
     */
    cout<<sizeof(A)<<endl; 
    return 0;
}
```

## 3.原则3

```c++
/**
 * @file morevir.cpp
 * @brief 对于包含虚函数的类,不管有多少个虚函数,只有一个虚指针,vptr的大小。
 * @author 光城
 * @version v1
 * @date 2019-07-21
 */
#include<iostream>
using namespace std;
class A{
    virtual void fun();
    virtual void fun1();
    virtual void fun2();
    virtual void fun3();
};
int main()
{
    cout<<sizeof(A)<<endl; // 8
    return 0;
}
```

## 4.原则4与5

```c++
/**
 * @file geninhe.cpp
 * @brief 1.普通单继承,继承就是基类+派生类自身的大小(注意字节对齐)
 * 注意:类的数据成员按其声明顺序加入内存,无访问权限无关,只看声明顺序。
 * 2.虚单继承,派生类继承基类vptr
 * @author 光城
 * @version v1
 * @date 2019-07-21
 */

#include<iostream>

using namespace std;

class A
{
    public:
        char a;
        int b;
};

/**
 * @brief 此时B按照顺序:
 * char a
 * int b
 * short a
 * long b
 * 根据字节对齐4+4+8+8=24
 * 
 * 或编译器优化
 * char a
 * short a
 * int b
 * long b
 * 根据字节对齐2+2+4+8=16
 */
class B:A
{
    public:
        short a;
        long b;
};
/**
* 把A的成员拆开看,char为1,int为4,所以是1+(3)+4+1+(3)=12,()为字节补齐
*/
class C
{
    A a;
    char c;
};

class A1
{
    virtual void fun(){}
};
class C1:public A1
{
};


int main()
{
    cout<<sizeof(A)<<endl; // 8
    cout<<sizeof(B)<<endl; // 16 或 24
    cout<<sizeof(C)<<endl; // 12

    /**
     * @brief 对于虚单函数继承,派生类也继承了基类的vptr,所以是8字节
     */
    cout<<sizeof(C1)<<endl; // 8 
    return 0;
}
```

## 5.原则6

```c++
/**
 * @file virnhe.cpp
 * @brief 虚继承
 * @author 光城
 * @version v1
 * @date 2019-07-21
 */

#include<iostream>
using namespace std;
class A
{
    virtual void fun() {}
};
class B
{
    virtual void fun2() {}
};
class C : virtual public  A, virtual public B
{
    public:
        virtual void fun3() {}
};

int main()
{
    /**
     * @brief 8 8 16  派生类虚继承多个虚函数,会继承所有虚函数的vptr
     */
    cout<<sizeof(A)<<" "<<sizeof(B)<<" "<<sizeof(C);

    return 0;
}
```



================================================
FILE: basic_content/sizeof/blackclass.cpp
================================================
/**
 * @file blackclass.cpp
 * @brief 空类的大小为1字节
 * @author 光城
 * @version v1
 * @date 2019-07-21
 */

#include <bits/stdc++.h>
#include <iostream>
using namespace std;
class A {};
int main() {
  cout << sizeof(A) << endl;
  return 0;
}


================================================
FILE: basic_content/sizeof/genA.cpp
================================================
/**
 * @file genA.cpp
 * @brief
 * 普通成员函数,大小为1,一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间。
 * @author 光城
 * @version v1
 * @date 2019-07-21
 */

#include <iostream>

using namespace std;

class A {
public:
  A();
  ~A();
  static int a;
  static void fun3();
  void fun();
  void fun1();
};

int main() {
  cout << sizeof(A) << endl; // 1
  return 0;
}


================================================
FILE: basic_content/sizeof/geninhe.cpp
================================================
/**
 * @file geninhe.cpp
 * @brief 1.普通单继承,继承就是基类+派生类自身的大小(注意字节对齐)
 * 注意:类的数据成员按其声明顺序加入内存,无访问权限无关,只看声明顺序。
 * 2.虚单继承,派生类继承基类vptr
 * @author 光城
 * @version v1
 * @date 2019-07-21
 */

#include <iostream>

using namespace std;

class A {
public:
  char a;
  int b;
};

/**
 * @brief 此时B按照顺序:
 * char a
 * int b
 * short a
 * long b
 * 根据字节对齐4+4+8+8=24
 *
 * 或编译器优化
 * char a
 * short a
 * int b
 * long b
 * 根据字节对齐2+2+4+8=16
 */
class B : A {
public:
  short a;
  long b;
};
/**
 * 把A的成员拆开看,char为1,int为4,所以是1+(3)+4+1+(3)=12,()为字节补齐
 */
class C {
  A a;
  char c;
};

class A1 {
  virtual void fun() {}
};
class C1 : public A1 {};

int main() {
  cout << sizeof(A) << endl; // 8
  cout << sizeof(B) << endl; // 16
  cout << sizeof(C) << endl; // 12

  /**
   * @brief 对于虚单函数继承,派生类也继承了基类的vptr,所以是8字节
   */
  cout << sizeof(C1) << endl; // 8
  return 0;
}


================================================
FILE: basic_content/sizeof/moreinhe.cpp
================================================
/**
 * @file moreinhe.cpp
 * @brief 普通多继承与虚函数多继承
 * @author 光城
 * @version v1
 * @date 2019-07-21
 */

#include <iostream>

using namespace std;

class A {
public:
  char a;
  int b;
};

class B {
public:
  short a;
  long b;
};

/**
 * @brief 8+16+8=32
 */
class C : A, B {
  char c;
};

int main() {
  cout << sizeof(A) << endl; // 8
  cout << sizeof(B) << endl; // 16
  cout << sizeof(C) << endl; // 32

  return 0;
}


================================================
FILE: basic_content/sizeof/morevir.cpp
================================================
/**
 * @file morevir.cpp
 * @brief 对于包含虚函数的类,不管有多少个虚函数,只有一个虚指针,vptr的大小。
 * @author 光城
 * @version v1
 * @date 2019-07-21
 */

#include <iostream>

using namespace std;

class A {

  virtual void fun();
  virtual void fun1();
  virtual void fun2();
  virtual void fun3();
};
int main() {
  cout << sizeof(A) << endl;
  return 0;
}


================================================
FILE: basic_content/sizeof/static.cpp
================================================
/**
 * @file static.cpp
 * @brief 静态数据成员
 * 静态数据成员被编译器放在程序的一个global data
 * members中,它是类的一个数据成员,但不影响类的大小。不管这个类产生了多少个实例,还是派生了多少新的类,静态数据成员只有一个实例。静态数据成员,一旦被声明,就已经存在。
 * @author 光城
 * @version v1
 * @date 2019-07-21
 */

#include <iostream>
using namespace std;
class A {
public:
  char b;
  virtual void fun(){};
  static int c;
  static int d;
  static int f;
};

int main() {

  /**
   * @brief 16  字节对齐、静态变量不影响类的大小、vptr指针=8
   */
  cout << sizeof(A) << endl;

  return 0;
}


================================================
FILE: basic_content/sizeof/virinhe.cpp
================================================
/**
 * @file virnhe.cpp
 * @brief 虚继承
 * @author 光城
 * @version v1
 * @date 2019-07-21
 */

#include <iostream>

using namespace std;

class A {
  virtual void fun() {}
};

class B {
  virtual void fun2() {}
};
class C : virtual public A, virtual public B {
public:
  virtual void fun3() {}
};

int main() {

  /**
   * @brief 8 8 16  派生类虚继承多个虚函数,会继承所有虚函数的vptr
   */
  cout << sizeof(A) << " " << sizeof(B) << " " << sizeof(C);

  return 0;
}


================================================
FILE: basic_content/sizeof/virmoreinhe.cpp
================================================
/**
 * @file virmoreinhe.cpp
 * @brief 虚函数多继承
 * @author 光城
 * @version v1
 * @date 2019-07-21
 */

#include <iostream>

using namespace std;

class A {
  virtual void fun() {}
};

class B {
  virtual void fun2() {}
};
class C : public A, public B {
public:
  virtual void fun3() {}
};

int main() {

  /**
   * @brief 8 8 16  派生类继承多个虚函数,会继承所有虚函数的vptr
   */
  cout << sizeof(A) << " " << sizeof(B) << " " << sizeof(C);

  return 0;
}


================================================
FILE: basic_content/static/BUILD
================================================
# please run `bazel run basic_content/static:nostatic_class`
# please run `bazel run basic_content/static:static_class`
# please run `bazel run basic_content/static:static_demo`
# please run `bazel run basic_content/static:static_error_variable`
# please run `bazel run basic_content/static:static_funciton`
# please run `bazel run basic_content/static:static_variable`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "nostatic_class",
    srcs = ["nostatic_class.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "static_class",
    srcs = ["static_class.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "static_demo",
    srcs = ["static_demo.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "sstatic_error_variable",
    srcs = ["static_error_variable.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "static_funciton",
    srcs = ["static_funciton.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "static_variable",
    srcs = ["static_variable.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/static/README.md
================================================
# static那些事

## 关于作者

微信公众号:

![](../img/wechat.jpg)

当与不同类型一起使用时,Static关键字具有不同的含义。我们可以使用static关键字:

**静态变量:** 函数中的变量,类中的变量

**静态类的成员:** 类对象和类中的函数

现在让我们详细看一下静态的这些用法:

**静态变量**

- 函数中的静态变量

当变量声明为static时,空间**将在程序的生命周期内分配**。即使多次调用该函数,静态变量的空间也**只分配一次**,前一次调用中的变量值通过下一次函数调用传递。这对于在C / C ++或需要存储先前函数状态的任何其他应用程序非常有用。

```c++
#include <iostream> 
#include <string> 
using namespace std; 

void demo() 
{ 
	// static variable 
	static int count = 0; 
	cout << count << " "; 
	
	// value is updated and 
	// will be carried to next 
	// function calls 
	count++; 
} 

int main() 
{ 
	for (int i=0; i<5; i++)	 
		demo(); 
	return 0; 
} 
```

输出:

```
0 1 2 3 4 
```

您可以在上面的程序中看到变量count被声明为static。因此,它的值通过函数调用来传递。每次调用函数时,都不会对变量计数进行初始化。

- 类中的静态变量

由于声明为static的变量只被初始化一次,因为它们在单独的静态存储中分配了空间,因此类中的静态变量**由对象共享**。对于不同的对象,不能有相同静态变量的多个副本。也是因为这个原因,静态变量不能使用构造函数初始化。

```c++

#include<iostream> 
using namespace std; 

class Apple 
{ 
public: 
	static int i; 
	
	Apple() 
	{ 
		// Do nothing 
	}; 
}; 

int main() 
{ 
Apple obj1; 
Apple obj2; 
obj1.i =2; 
obj2.i = 3; 
	
// prints value of i 
cout << obj1.i<<" "<<obj2.i; 
} 
```

您可以在上面的程序中看到我们已经尝试为多个对象创建静态变量i的多个副本。但这并没有发生。因此,类中的静态变量应由用户使用类外的类名和范围解析运算符显式初始化,如下所示:

```c++

#include<iostream> 
using namespace std; 

class Apple 
{ 
public: 
	static int i; 
	
	Apple() 
	{ 
		// Do nothing 
	}; 
}; 

int Apple::i = 1; 

int main() 
{ 
	Apple obj; 
	// prints value of i 
	cout << obj.i; 
} 
```

输出:

```
1
```

**静态成员**

- 类对象为静态

就像变量一样,对象也在声明为static时具有范围,直到程序的生命周期。

考虑以下程序,其中对象是非静态的。

```c++
#include<iostream> 
using namespace std; 

class Apple 
{ 
	int i; 
	public: 
		Apple() 
		{ 
			i = 0; 
			cout << "Inside Constructor\n"; 
		} 
		~Apple() 
		{ 
			cout << "Inside Destructor\n"; 
		} 
}; 

int main() 
{ 
	int x = 0; 
	if (x==0) 
	{ 
		Apple obj; 
	} 
	cout << "End of main\n"; 
} 

```


输出:

```c++
Inside Constructor
Inside Destructor
End of main
```

在上面的程序中,对象在if块内声明为非静态。因此,变量的范围仅在if块内。因此,当创建对象时,将调用构造函数,并且在if块的控制权越过析构函数的同时调用,因为对象的范围仅在声明它的if块内。
如果我们将对象声明为静态,现在让我们看看输出的变化。

```c++
#include<iostream> 
using namespace std; 

class Apple 
{ 
	int i; 
	public: 
		Apple() 
		{ 
			i = 0; 
			cout << "Inside Constructor\n"; 
		} 
		~Apple() 
		{ 
			cout << "Inside Destructor\n"; 
		} 
}; 

int main() 
{ 
	int x = 0; 
	if (x==0) 
	{ 
		static Apple obj; 
	} 
	cout << "End of main\n"; 
} 

```


输出:

```
Inside Constructor
End of main
Inside Destructor
```

您可以清楚地看到输出的变化。现在,在main结束后调用析构函数。这是因为静态对象的范围是贯穿程序的生命周期。

- 类中的静态函数

就像类中的静态数据成员或静态变量一样,静态成员函数也不依赖于类的对象。我们被允许使用对象和'.'来调用静态成员函数。但建议使用类名和范围解析运算符调用静态成员。

允许静态成员函数仅访问静态数据成员或其他静态成员函数,它们无法访问类的非静态数据成员或成员函数。

```c++
#include<iostream> 
using namespace std; 

class Apple 
{ 
    public: 
        // static member function 
        static void printMsg() 
        {
            cout<<"Welcome to Apple!"; 
        }
}; 

// main function 
int main() 
{ 
    // invoking a static member function 
    Apple::printMsg(); 
} 
```

输出:

```
Welcome to Apple!
```

**限定访问范围**
static还有限定访问范围的作用(类似于匿名名字空间)。来自issue:https://github.com/Light-City/CPlusPlusThings/issues/142
```cpp
// source1.cpp
extern void sayHello();
const char* msg = "Hello World!\n";
int main()
{
    sayHello();
    return 0;
}

// source2.cpp
#include <cstdio>
extern char* msg;
void sayHello()
{
    printf("%s", msg);
}
```
g++对于上面两个代码文件是可以正常编译并且打印Hello World!,但如果给source1.cpp中的msg加上static,则会导致undefined reference to 'msg'的编译错误:
```cpp
// source1.cpp
extern void sayHello();
static const char* msg = "Hello World!\n";
int main()
{
    sayHello();
    return 0;
}
```


================================================
FILE: basic_content/static/nostatic_class.cpp
================================================
#include <iostream>
using namespace std;

class Apple {
  int i;

public:
  Apple() {
    i = 0;
    cout << "Inside Constructor\n";
  }
  ~Apple() { cout << "Inside Destructor\n"; }
};

int main() {
  int x = 0;
  if (x == 0) {
    Apple obj;
  }
  cout << "End of main\n";
}


================================================
FILE: basic_content/static/static_class.cpp
================================================
#include <iostream>
using namespace std;

class Apple {
  int i;

public:
  Apple() {
    i = 0;
    cout << "Inside Constructor\n";
  }
  ~Apple() { cout << "Inside Destructor\n"; }
};

int main() {
  int x = 0;
  if (x == 0) {
    static Apple obj;
  }
  cout << "End of main\n";
}


================================================
FILE: basic_content/static/static_demo.cpp
================================================
// the use of static Static
// variables in a Function
#include <iostream>
#include <string>
using namespace std;

void demo() {
  // static variable
  static int count = 0;
  cout << count << " ";

  // value is updated and
  // will be carried to next
  // function calls
  count++;
}

int main() {
  for (int i = 0; i < 5; i++)
    demo();
  return 0;
}


================================================
FILE: basic_content/static/static_error_variable.cpp
================================================
// variables inside a class

#include <iostream>
using namespace std;

class Apple {
public:
  static int i;

  Apple(){
      // Do nothing
  };
};

int main() {
  Apple obj1;
  Apple obj2;
  obj1.i = 2;
  obj2.i = 3;

  // prints value of i
  cout << obj1.i << " " << obj2.i;
}


================================================
FILE: basic_content/static/static_funciton.cpp
================================================
#include <iostream>
using namespace std;

class Apple {
public:
  // static member function
  static void printMsg() { cout << "Welcome to Apple!"; }
};

// main function
int main() {
  // invoking a static member function
  Apple::printMsg();
}


================================================
FILE: basic_content/static/static_variable.cpp
================================================
// variables inside a class

#include <iostream>
using namespace std;

class GfG {
public:
  static int i;

  GfG(){
      // Do nothing
  };
};

int GfG::i = 1;

int main() {
  GfG obj;
  // prints value of i
  cout << obj.i;
}


================================================
FILE: basic_content/struct/BUILD
================================================
# please run `bazel run basic_content/struct:ext_struct_func`
# please run `bazel run basic_content/struct:struct_func_func`
# please run `bazel run basic_content/struct:struct_func`
# please run `bazel run basic_content/struct:struct_func_cpp`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "ext_struct_func",
    srcs = ["ext_struct_func.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "struct_func_func",
    srcs = ["struct_func_func.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "struct_func",
    srcs = ["struct_func.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "struct_func_cpp",
    srcs = ["struct_func.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/struct/README.md
================================================
# 一文搞懂C和C++中struct

## 关于作者:

个人公众号:

![](../img/wechat.jpg)

## 1.C中struct

- 在C中struct只单纯的用作数据的复合类型,也就是说,在结构体声明中只能将数据成员放在里面,而不能将函数放在里面。 
- 在C结构体声明中不能使用C++访问修饰符,如:public、protected、private 而在C++中可以使用。
- 在C中定义结构体变量,如果使用了下面定义必须加struct。
- C的结构体不能继承(没有这一概念)。
- 若结构体的名字与函数名相同,可以正常运行且正常的调用!例如:可以定义与 struct Base 不冲突的 void Base() {}。

完整案例:

```c
#include<stdio.h>

struct Base {            // public
    int v1; 
//    public:      //error
        int v2; 
    //private:
        int v3; 
    //void print(){       // c中不能在结构体中嵌入函数
    //    printf("%s\n","hello world");
    //};    //error!
};

void Base(){
    printf("%s\n","I am Base func");
}
//struct Base base1;  //ok
//Base base2; //error
int main() {
    struct Base base;
    base.v1=1;
    //base.print();
    printf("%d\n",base.v1);
    Base();
    return 0;
}
```

最后输出:

```
1
I am Base func
```

完整代码见:[struct_func.c](./struct_func.c)

## 2.C++中struct

与C对比如下:

- C++结构体中不仅可以定义数据,还可以定义函数。
- C++结构体中可以使用访问修饰符,如:public、protected、private 。
- C++结构体使用可以直接使用不带struct。
- C++继承
- 若结构体的名字与函数名相同,可以正常运行且正常的调用!但是定义结构体变量时候只能用带struct的!

例如:

> 情形1:不适用typedef定义结构体别名

未添加同名函数前:

```c++
struct Student {
    
};
//Student(){}
struct Student s; //ok
Student s;  //ok
```

添加同名函数后:

```c++
struct Student {
    
};
Student(){}
struct Student s; //ok
Student s;  //error
```

> 情形二:使用typedef定义结构体别名

```c++
typedef struct Base1 {         
    int v1;
    int v3;
    public:     //显示声明public
    int v2;
    void print(){       
        printf("%s\n","hello world");
    };    
}B;
//void B() {}  //error! 符号 "B" 已经被定义为一个 "struct Base1" 的别名
```

> 前三种案例

```c++
#include<iostream>
#include<stdio.h>

struct Base {         
    int v1;
//    private:   //error!
        int v3;
    public:     //显示声明public
        int v2;
    void print(){       
        printf("%s\n","hello world");
    };    
};

int main() {
    struct Base base1;  //ok
    Base base2; //ok
    Base base;
    base.v1=1;
    base.v3=2;
    base.print();
    printf("%d\n",base.v1);
    printf("%d\n",base.v3);
    return 0;
}
```

完整代码见:[struct_func.cpp](struct_func.cpp)

> 继承案例

```c++
#include<iostream>
#include<stdio.h>
struct Base {         
    int v1;
//    private:   //error!
        int v3;
    public:   //显示声明public
        int v2;
    virtual void print(){       
        printf("%s\n","Base");
    };    
};
struct Derived:Base {         

    public:
        int v2;
    void print(){       
        printf("%s\n","Derived");
    };    
};
int main() {
    Base *b=new Derived();
    b->print();
    return 0;
}
```

完整代码见:[ext_struct_func.cpp](./ext_struct_func.cpp)

> 同名函数

```c++
#include<iostream>
#include<stdio.h>

struct Base {         
    int v1;
//    private:   //error!
        int v3;
    public:     //显示声明public
        int v2;
    void print(){       
        printf("%s\n","hello world");
    };    
};

typedef struct Base1 {         
    int v1;
//    private:   //error!
        int v3;
    public:     //显示声明public
        int v2;
    void print(){       
        printf("%s\n","hello world");
    };    
}B;
void Base(){
    printf("%s\n","I am Base func");
}
//void B() {}  //error! 符号 "B" 已经被定义为一个 "struct Base1" 的别名
int main() {
    struct Base base;  //ok
    //Base base1;  // error!
    base.v1=1;
    base.v3=2;
    base.print();
    printf("%d\n",base.v1);
    printf("%d\n",base.v3);
    Base();
    return 0;
}
```
完整代码见:[struct_func_func.cpp](./struct_func_func.cpp)

## 3.总结

### C和C++中的Struct区别

| C                                                      | C++                                                          |
| ------------------------------------------------------ | ------------------------------------------------------------ |
| 不能将函数放在结构体声明                               | 能将函数放在结构体声明                                       |
| 在C结构体声明中不能使用C++访问修饰符。                 | public、protected、private 在C++中可以使用。                 |
| 在C中定义结构体变量,如果使用了下面定义必须加struct。  | 可以不加struct                                               |
| 结构体不能继承(没有这一概念)。                       | 可以继承                                                     |
| 若结构体的名字与函数名相同,可以正常运行且正常的调用! | 若结构体的名字与函数名相同,使用结构体,只能使用带struct定义! |


================================================
FILE: basic_content/struct/ext_struct_func.cpp
================================================
#include <iostream>
#include <stdio.h>
using namespace std;
struct Base {
  int v1;
  //    private:   //error!
  int v3;

public: // 显示声明public
  int v2;
  virtual void print() { printf("%s\n", "Base"); };
  Base() { cout << "Base construct" << endl; };
  virtual ~Base() { cout << "Base deconstruct" << endl; };
};

struct Derived : Base {

  Derived() { cout << "Derived construct" << endl; };
  virtual ~Derived() { cout << "Derived deconstruct" << endl; };

public:
  int v2;
  void print() { printf("%s\n", "Derived"); };
};

int main() {
  Base *b = new Derived();
  b->print();
  delete b;
  return 0;
}


================================================
FILE: basic_content/struct/struct_func.c
================================================
#include <stdio.h>

struct Base
{ // public
    int v1;
    //    public:      //error
    int v2;
    // private:
    int v3;
    // void print(){       // c中不能在结构体中嵌入函数
    //     printf("%s\n","hello world");
    // };    //error!
};

void Base()
{
    printf("%s\n", "I am Base func");
}
// struct Base base1;  //ok
// Base base2; //error

int main()
{
    struct Base base;
    base.v1 = 1;
    // base.print();
    printf("%d\n", base.v1);
    Base();
    return 0;
}


================================================
FILE: basic_content/struct/struct_func.cpp
================================================
#include <iostream>
#include <stdio.h>

struct Base {
  int v1;
  //    private:   //error!
  int v3;

public: // 显示声明public
  int v2;
  void print() { printf("%s\n", "hello world"); };
};

int main() {
  struct Base base1; // ok
  Base base2;        // ok
  Base base;
  base.v1 = 1;
  base.v3 = 2;
  base.print();
  printf("%d\n", base.v1);
  printf("%d\n", base.v3);
  return 0;
}


================================================
FILE: basic_content/struct/struct_func_func.cpp
================================================
#include <iostream>
#include <stdio.h>

struct Base {
  int v1;
  //    private:   //error!
  int v3;

public: // 显示声明public
  int v2;
  void print() { printf("%s\n", "hello world"); };
};

typedef struct Base1 {
  int v1;
  //    private:   //error!
  int v3;

public: // 显示声明public
  int v2;
  void print() { printf("%s\n", "hello world"); };
} B;
void Base() { printf("%s\n", "I am Base func"); }
// void B() {}  //error! 符号 "B" 已经被定义为一个 "struct Base1" 的别名
int main() {
  struct Base base; // ok
  // Base base1;  // error!
  base.v1 = 1;
  base.v3 = 2;
  base.print();
  printf("%d\n", base.v1);
  printf("%d\n", base.v3);
  Base();
  return 0;
}


================================================
FILE: basic_content/struct_class/README.md
================================================
# struct与class区别

## 关于作者:

个人公众号:

![](../img/wechat.jpg)

关于C与C++中struct内容:见[struct那些事](../struct)

总的来说,struct 更适合看成是一个数据结构的实现体,class 更适合看成是一个对象的实现体。

区别:

最本质的一个区别就是默认的访问控制

默认的继承访问权限。struct 是 public 的,class 是 private 的。

struct 作为数据结构的实现体,它默认的数据访问控制是 public 的,而 class 作为对象的实现体,它默认的成员变量访问控制是 private 的。


================================================
FILE: basic_content/this/BUILD
================================================
# please run `bazel run basic_content/this:person`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "person",
    srcs = ["person.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/this/README.md
================================================
# this指针那些事

## 关于作者

微信公众号:

![](../img/wechat.jpg)

## 1.this指针

相信在坐的很多人,都在学Python,对于Python来说有self,类比到C++中就是this指针,那么下面一起来深入分析this指针在类中的使用!

首先来谈谈this指针的用处:

(1)一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。

(2)this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。也就是说,即使你没有写上this指针,编译器在编译的时候也是加上this的,它作为非静态成员函数的隐含形参,对各成员的访问均通过this进行。

其次,this指针的使用:

(1)在类的非静态成员函数中返回类对象本身的时候,直接使用 return *this。

(2)当参数与成员变量名相同时,如this->n = n (不能写成n = n)。

另外,在网上大家会看到this会被编译器解析成`A *const `,`A const * `,究竟是哪一个呢?下面通过断点调试分析:

现有如下例子:

```c++
#include<iostream>
#include<cstring>


using namespace std;
class Person{
public:
    typedef enum {
        BOY = 0, 
        GIRL 
    }SexType;
    Person(char *n, int a,SexType s){
        name=new char[strlen(n)+1];
        strcpy(name,n);
        age=a;
        sex=s;
    }
    int get_age() const{
    
        return this->age; 
    }
    Person& add_age(int a){
        age+=a;
        return *this; 
    }
    ~Person(){
        delete [] name;
    }
private:
    char * name;
    int age;
    SexType sex;
};


int main(){
    Person p("zhangsan",20,Person::BOY); 
    cout<<p.get_age()<<endl;
	cout<<p.add_age(10).get_age()<<endl;
    return 0;
}
```

对于这个简单的程序,相信大家没得问题吧,就是定义了一个类,然后初始化构造函数,并获取这个人的年龄,设置后,再获取!

为了验证this指针是哪一个,现在在`add_age`处添加断点,运行后如下:

![thiscontrust](./img/thiscontrust.png)

![genthis](./img/genthis.png)

会发现编译器自动为我们加上`A* const`,而不是`A const *this`!

紧接着,上述还有个常函数,那么我们在对`get_age`添加断点,如下:

![constthis](./img/constthis.png)

会发现编译器把上述的this,变为`const A* const`,这个大家也能想到,因为这个函数是const函数,那么针对const函数,它只能访问const变量与const函数,不能修改其他变量的值,所以需要一个this指向不能修改的变量,那就是`const A*`,又由于本身this是`const`指针,所以就为`const A* const`!

总结:this在成员函数的开始执行前构造,在成员的执行结束后清除。上述的get_age函数会被解析成`get_age(const A * const this)`,`add_age`函数会被解析成`add_age(A* const this,int a)`。在C++中类和结构是只有一个区别的:类的成员默认是private,而结构是public。this是类的指针,如果换成结构,那this就是结构的指针了。


================================================
FILE: basic_content/this/person.cpp
================================================
#include <cstring>
#include <iostream>

using namespace std;
class Person {
public:
  typedef enum { BOY = 0, GIRL } SexType;
  Person(char *n, int a, SexType s) {
    name = new char[strlen(n) + 1];
    strcpy(name, n);
    age = a;
    sex = s;
  }
  int get_age() const { return this->age; }
  Person &add_age(int a) {
    age += a;
    return *this;
  }
  ~Person() { delete[] name; }

private:
  char *name;
  int age;
  SexType sex;
};

int main() {
  Person p("zhangsan", 20, Person::BOY);
  cout << p.get_age() << endl;

  return 0;
}


================================================
FILE: basic_content/union/BUILD
================================================
# please run `bazel run basic_content/union:union`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "union",
    srcs = ["union.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/union/README.md
================================================
# UNION那些事

## 关于作者:

个人公众号:

![](../img/wechat.jpg)

联合(union)是一种节省空间的特殊的类,一个 union 可以有多个数据成员,但是在任意时刻只有一个数据成员可以有值。当某个成员被赋值后其他成员变为未定义状态。联合有如下特点:

- 默认访问控制符为 public
- 可以含有构造函数、析构函数
- 不能含有引用类型的成员
- 不能继承自其他类,不能作为基类
- 不能含有虚函数
- 匿名 union 在定义所在作用域可直接访问 union 成员
- 匿名 union 不能包含 protected 成员或 private 成员
- 全局匿名联合必须是静态(static)的


================================================
FILE: basic_content/union/union.cpp
================================================
/**
 * @file union.cpp
 * @brief UNION
 * @author 光城
 * @version v1
 * @date 2019-08-06
 */

#include <iostream>
/**
 * 默认访问控制符为public
 */
union UnionTest {
  /**
   * 可以含有构造函数、析构函数
   */
  UnionTest() : i(10) { print(i); };
  ~UnionTest(){};
  int i;

private:
  void print(int i) { std::cout << i << std::endl; };
};
/**
 * 全局匿名联合必须是静态的
 */
static union {
  int i;
  double d;
};

int main() {
  UnionTest u;

  union {
    int i;
    double d;
  };

  std::cout << u.i << std::endl; // 输出 UnionTest 联合的 10

  ::i = 20;
  std::cout << ::i << std::endl; // 输出全局静态匿名联合的 20
  /**
   * 匿名union在定义所在作用域可直接访问union成员
   */
  i = 30;
  std::cout << i << std::endl; // 输出局部匿名联合的 30

  return 0;
}


================================================
FILE: basic_content/using/BUILD
================================================
# please run `bazel run basic_content/using:derived_base`
# please run `bazel run basic_content/using:using_derived`
# please run `bazel run basic_content/using:using_global`
# please run `bazel run basic_content/using:using_typedef`
load("@rules_cc//cc:defs.bzl", "cc_binary")

# Don't panic if you get compilation errors, this is what this code demonstrates, as expected.
cc_binary(
    name = "derived_base",
    srcs = ["derived_base.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "using_derived",
    srcs = ["using_derived.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "using_global",
    srcs = ["using_global.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "using_typedef",
    srcs = ["using_typedef.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/using/README.md
================================================
# using那些事
## 关于作者:

个人公众号:

![](../img/wechat.jpg)

## 基本使用

局部与全局using,具体操作与使用见下面案例:

```c++
#include <iostream>
#define isNs1 1
//#define isGlobal 2
using namespace std;
void func() 
{
    cout<<"::func"<<endl;
}

namespace ns1 {
    void func()
    {
        cout<<"ns1::func"<<endl; 
    }
}

namespace ns2 {
#ifdef isNs1 
    using ns1::func;    /// ns1中的函数
#elif isGlobal
    using ::func; /// 全局中的函数
#else
    void func() 
    {
        cout<<"other::func"<<endl; 
    }
#endif
}

int main() 
{
    /**
     * 这就是为什么在c++中使用了cmath而不是math.h头文件
     */
    ns2::func(); // 会根据当前环境定义宏的不同来调用不同命名空间下的func()函数
    return 0;
}
```
完整代码见:[using_global.cpp](using_global.cpp)
## 改变访问性

```
class Base{
public:
 std::size_t size() const { return n;  }
protected:
 std::size_t n;
};
class Derived : private Base {
public:
 using Base::size;
protected:
 using Base::n;
};
```

类Derived私有继承了Base,对于它来说成员变量n和成员函数size都是私有的,如果使用了using语句,可以改变他们的可访问性,如上述例子中,size可以按public的权限访问,n可以按protected的权限访问。
完整代码见:[derived_base.cpp](derived_base.cpp)
## 函数重载

在继承过程中,派生类可以覆盖重载函数的0个或多个实例,一旦定义了一个重载版本,那么其他的重载版本都会变为不可见。

如果对于基类的重载函数,我们需要在派生类中修改一个,又要让其他的保持可见,必须要重载所有版本,这样十分的繁琐。

```c++
#include <iostream>
using namespace std;

class Base{
    public:
        void f(){ cout<<"f()"<<endl;
        }
        void f(int n){
            cout<<"Base::f(int)"<<endl;
        }
};

class Derived : private Base {
    public:
        using Base::f;
        void f(int n){
            cout<<"Derived::f(int)"<<endl;
        }
};

int main()
{
    Base b;
    Derived d;
    d.f();
    d.f(1);
    return 0;
}
```
如上代码中,在派生类中使用using声明语句指定一个名字而不指定形参列表,所以一条基类成员函数的using声明语句就可以把该函数的所有重载实例添加到派生类的作用域中。此时,派生类只需要定义其特有的函数就行了,而无需为继承而来的其他函数重新定义。

完整代码见:[using_derived.cpp](using_derived.cpp)
## 取代typedef

C中常用typedef A B这样的语法,将B定义为A类型,也就是给A类型一个别名B

对应typedef A B,使用using B=A可以进行同样的操作。

```c++
typedef vector<int> V1; 
using V2 = vector<int>;
```
完整代码见:[using_typedef.cpp](using_typedef.cpp)


================================================
FILE: basic_content/using/derived_base.cpp
================================================
#include <iostream>

using namespace std;

class Base1 {
public:
  Base1() : value(10) {}
  virtual ~Base1() {}
  void test1() { cout << "Base test1..." << endl; }

protected: // 保护
  int value;
};
// 默认为私有继承
class Derived1 : Base1 {
public:
  void test2() { cout << "value is " << value << endl; }
};

class Base {
public:
  Base() : value(20) {}
  virtual ~Base() {}
  void test1() { cout << "Base test1..." << endl; }

private: // 私有
  int value;
};

/**
 * 子类对父类成员的访问权限跟如何继承没有任何关系,
 * “子类可以访问父类的public和protected成员,不可以访问父类的private成员”——这句话对任何一种继承都是成立的。
 *
 */
class Derived : Base {
public:
  using Base::value;
  void test2() { cout << "value is " << value << endl; }
};

int main() {
  Derived1 d1;
  d1.test2();

  Derived d;
  d.test2();
  return 0;
}


================================================
FILE: basic_content/using/using_derived.cpp
================================================
/**
 * @file using_derived.cpp
 * @brief 函数重装
 * @author 光城
 * @version v1
 * @date 2019-08-07
 */

#include <iostream>
using namespace std;

class Base {
public:
  void f() { cout << "f()" << endl; }
  void f(int n) { cout << "Base::f(int)" << endl; }
};

class Derived : private Base {
public:
  using Base::f;
  void f(int n) { cout << "Derived::f(int)" << endl; }
};

int main() {
  Derived d;
  d.f();
  d.f(1);
  return 0;
}


================================================
FILE: basic_content/using/using_global.cpp
================================================
/**
 * @file using_global.cpp
 * @brief using各种使用
 * @author 光城
 * @version v1
 * @date 2019-08-07
 */

#include <iostream>
#define isNs1 1
// #define isGlobal 2
using namespace std;
void func() { cout << "::func" << endl; }

namespace ns1 {
void func() { cout << "ns1::func" << endl; }
} // namespace ns1

namespace ns2 {
#ifdef isNs1
using ns1::func; /// ns1中的函数
#elif isGlobal
using ::func; /// 全局中的函数
#else
void func() { cout << "other::func" << endl; }
#endif
} // namespace ns2

int main() {
  /**
   * 这就是为什么在c++中使用了cmath而不是math.h头文件
   */
  ns2::func(); // 会根据当前环境定义宏的不同来调用不同命名空间下的func()函数
  return 0;
}


================================================
FILE: basic_content/using/using_typedef.cpp
================================================
/**
 * @file using_typedef.cpp
 * @brief bazel run basic_content/using:using_typedef
 * 取代typedef,使用using来定义别名
 * @author 光城
 * @version v1
 * @date 2019-08-07
 */

#include <iostream>
#include <vector>
using namespace std;

typedef vector<int> V1;
using V2 = vector<int>;

int main() {
  int nums1[] = {1, 2, 3, 4, 5, 6};
  V1 vec1(nums1, nums1 + sizeof(nums1) / sizeof(int));
  int nums2[] = {5, 7, 6};
  V2 vec2(nums2, nums2 + sizeof(nums2) / sizeof(int));

  for (auto i : vec1)
    cout << i << " ";
  cout << endl;

  for (auto i : vec2)
    cout << i << " ";
  cout << endl;

  return 0;
}


================================================
FILE: basic_content/virtual/README.md
================================================
# virtual那些事

## 关于作者:

个人公众号:

![](../img/wechat.jpg)

## 1.虚函数与运行多态

对应的代码:[emp.cpp](./set1/emp.cpp)

**虚函数的调用取决于指向或者引用的对象的类型,而不是指针或者引用自身的类型。**

## 2.vptr与vtable

见[vptr_vtable那些事](../vptr_vtable)

## 3.虚函数中默认参数

对应的代码:[default_arg.cpp](./set2/default_arg.cpp)

**默认参数是静态绑定的,虚函数是动态绑定的。 默认参数的使用需要看指针或者引用本身的类型,而不是对象的类型**。

## 4.可以不可以

(1) **静态函数可以声明为虚函数吗?**

原因主要有两方面:

**静态函数不可以声明为虚函数,同时也不能被const 和 volatile关键字修饰**

static成员函数不属于任何类对象或类实例,所以即使给此函数加上virutal也是没有任何意义

虚函数依靠vptr和vtable来处理。vptr是一个指针,在类的构造函数中创建生成,并且只能用this指针来访问它,静态成员函数没有this指针,所以无法访问vptr。

代码学习:[static_error.cpp  ](./set3/static_error.cpp  )

(2)**构造函数可以为虚函数吗?**

构造函数不可以声明为虚函数。同时除了inline|explicit之外,构造函数不允许使用其它任何关键字。

为什么构造函数不可以为虚函数?

尽管虚函数表vtable是在编译阶段就已经建立的,但指向虚函数表的指针vptr是在运行阶段实例化对象时才产生的。 如果类含有虚函数,编译器会在构造函数中添加代码来创建vptr。 问题来了,如果构造函数是虚的,那么它需要vptr来访问vtable,可这个时候vptr还没产生。 因此,构造函数不可以为虚函数。

我们之所以使用虚函数,是因为需要在信息不全的情况下进行多态运行。而构造函数是用来初始化实例的,实例的类型必须是明确的。 因此,构造函数没有必要被声明为虚函数。

代码学习:

- [copy_consrtuct.cpp](./set3/copy_consrtuct.cpp) 

- [vir_con.cpp](./set3/vir_con.cpp) 

(3)**析构函数可以为虚函数吗?**

**析构函数可以声明为虚函数。如果我们需要删除一个指向派生类的基类指针时,应该把析构函数声明为虚函数。 事实上,只要一个类有可能会被其它类所继承, 就应该声明虚析构函数(哪怕该析构函数不执行任何操作)。**

代码学习:

- [full_virde.cpp](./set3/full_virde.cpp)

- [vir_de.cpp ](./set3/vir_de.cpp)      

(4)**虚函数可以为私有函数吗?**

- 基类指针指向继承类对象,则调用继承类对象的函数;
- int main()必须声明为Base类的友元,否则编译失败。 编译器报错: ptr无法访问私有函数。 当然,把基类声明为public, 继承类为private,该问题就不存在了。

代码学习:

- [virtual_function.cpp](./set3/virtual_function.cpp)
- [virtual_function1.cpp](./set3/virtual_function1.cpp)

(5)**虚函数可以被内联吗?**

**通常类成员函数都会被编译器考虑是否进行内联。 但通过基类指针或者引用调用的虚函数必定不能被内联。 当然,实体对象调用虚函数或者静态调用时可以被内联,虚析构函数的静态调用也一定会被内联展开。**

- 虚函数可以是内联函数,内联是可以修饰虚函数的,但是当虚函数表现多态性的时候不能内联。
- 内联是在编译器建议编译器内联,而虚函数的多态性在运行期,编译器无法知道运行期调用哪个代码,因此虚函数表现为多态性时(运行期)不可以内联。
- `inline virtual` 唯一可以内联的时候是:编译器知道所调用的对象是哪个类(如 `Base::who()`),这只有在编译器具有实际对象而不是对象的指针或引用时才会发生。

代码学习:

- [virtual_inline.cpp](./set3/virtual_inline.cpp)

- [inline_virtual.cpp](./set3/inline_virtual.cpp)

## 5.RTTI与dynamic_cast

RTTI(Run-Time Type Identification),通过运行时类型信息程序能够使用[基类](https://baike.baidu.com/item/%E5%9F%BA%E7%B1%BB/9589663)的[指针](https://baike.baidu.com/item/%E6%8C%87%E9%92%88/2878304)或引用来检查这些指针或引用所指的对象的实际[派生类](https://baike.baidu.com/item/%E6%B4%BE%E7%94%9F%E7%B1%BB)型。

在面向对象程序设计中,有时我们需要在运行时查询一个对象是否能作为某种多态类型使用。与Java的instanceof,以及C#的as、is运算符类似,C++提供了dynamic_cast函数用于动态转型。相比C风格的强制类型转换和C++ reinterpret_cast,dynamic_cast提供了类型安全检查,是一种基于能力查询(Capability Query)的转换,所以在多态类型间进行转换更提倡采用dynamic_cast。

代码学习:

- [rtti.cpp](./set4/rtti.cpp)
- [warn_rtti.cpp](./set4/warn_rtti.cpp)

## 6.纯虚函数和抽象类

见[纯虚函数和抽象类那些事](../abstract)


================================================
FILE: basic_content/virtual/set1/BUILD
================================================
# please run `bazel run basic_content/virtual/set1:emp`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "emp",
    srcs = ["emp.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/virtual/set1/emp.cpp
================================================
#include <iostream>
using namespace std;

class Employee {
public:
  virtual void raiseSalary() { cout << 0 << endl; }

  virtual void promote() { /* common promote code */
  }
};

class Manager : public Employee {
  virtual void raiseSalary() { cout << 100 << endl; }

  virtual void promote() { /* Manager specific promote */
  }
};
class Engineer : public Employee {
  virtual void raiseSalary() { cout << 200 << endl; }

  virtual void promote() { /* Manager specific promote */
  }
};

// Similarly, there may be other types of employees
// We need a very simple function to increment salary of all employees
// Note that emp[] is an array of pointers and actual pointed objects can
// be any type of employees. This function should ideally be in a class
// like Organization, we have made it global to keep things simple
void globalRaiseSalary(Employee *emp[], int n) {
  for (int i = 0; i < n; i++)
    emp[i]->raiseSalary(); // Polymorphic Call: Calls raiseSalary()
                           // according to the actual object, not
                           // according to the type of pointer
}
int main() {
  Employee *emp[] = {new Manager(), new Engineer};
  globalRaiseSalary(emp, 2);
  return 0;
}


================================================
FILE: basic_content/virtual/set2/BUILD
================================================
# please run `bazel run basic_content/virtual/set2:default_arg`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "default_arg",
    srcs = ["default_arg.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/virtual/set2/default_arg.cpp
================================================
/**
 * @file first_example.cpp
 * @brief 虚函数中默认参数
 * 规则:虚函数是动态绑定的,默认参数是静态绑定的。默认参数的使用需要看指针或者应用本身的类型,而不是对象的类型!
 * @author 光城
 * @version v1
 * @date 2019-07-24
 */

#include <iostream>
using namespace std;

class Base {
public:
  virtual void fun(int x = 10) { cout << "Base::fun(), x = " << x << endl; }
};

class Derived : public Base {
public:
  virtual void fun(int x = 20) { cout << "Derived::fun(), x = " << x << endl; }
};

int main() {
  Derived d1;
  Base *bp = &d1;
  bp->fun(); // 10
  return 0;
}


================================================
FILE: basic_content/virtual/set3/BUILD
================================================
# please run `bazel run //basic_content/virtual/set3:copy_consrtuct`
# please run `bazel run //basic_content/virtual/set3:full_virde`
# please run `bazel run //basic_content/virtual/set3:inline_virtual`
# please run `bazel run //basic_content/virtual/set3:vir_con`
# please run `bazel run //basic_content/virtual/set3:vir_de`
# please run `bazel run //basic_content/virtual/set3:virtual_function`
# please run `bazel run //basic_content/virtual/set3:virtual_function1`
# please run `bazel run //basic_content/virtual/set3:virtual_inline`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "copy_consrtuct",
    srcs = ["copy_consrtuct.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "full_virde",
    srcs = ["full_virde.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "inline_virtual",
    srcs = ["inline_virtual.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "vir_con",
    srcs = ["vir_con.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "vir_de",
    srcs = ["vir_de.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "virtual_function",
    srcs = ["virtual_function.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "virtual_function1",
    srcs = ["virtual_function1.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "virtual_inline",
    srcs = ["virtual_inline.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/virtual/set3/copy_consrtuct.cpp
================================================
#include <iostream>
using namespace std;

class Base {
public:
};

class Derived : public Base {
public:
  Derived() { cout << "Derived created" << endl; }

  Derived(const Derived &rhs) {
    cout << "Derived created by deep copy" << endl;
  }

  ~Derived() { cout << "Derived destroyed" << endl; }
};

int main() {
  Derived s1;

  Derived s2 = s1; // Compiler invokes "copy constructor"
  // Type of s1 and s2 are concrete to compiler

  // How can we create Derived1 or Derived2 object
  // from pointer (reference) to Base class pointing Derived object?

  return 0;
}


================================================
FILE: basic_content/virtual/set3/full_virde.cpp
================================================
/**
 * @file full_virde.cpp
 * @brief 将基类的析构函数声明为虚函数
 * 输出结果:
 *      Constructing base
 *      Constructing derived
 *      Destructing derived
 *      Destructing base
 * @author 光城
 * @version v1
 * @date 2019-07-24
 */
#include <iostream>

using namespace std;

class base {
public:
  base() { cout << "Constructing base \n"; }
  virtual ~base() { cout << "Destructing base \n"; }
};

class derived : public base {
public:
  derived() { cout << "Constructing derived \n"; }
  ~derived() { cout << "Destructing derived \n"; }
};

int main(void) {
  derived *d = new derived();
  base *b = d;
  delete b;
  return 0;
}


================================================
FILE: basic_content/virtual/set3/inline_virtual.cpp
================================================
#include <iostream>
using namespace std;
class Base {
public:
  inline virtual void who() { cout << "I am Base\n"; }
  virtual ~Base() {}
};
class Derived : public Base {
public:
  inline void who() // 不写inline时隐式内联
  {
    cout << "I am Derived\n";
  }
};

int main() {
  // 此处的虚函数
  // who(),是通过类(Base)的具体对象(b)来调用的,编译期间就能确定了,所以它可以是内联的,但最终是否内联取决于编译器。
  Base b;
  b.who();

  // 此处的虚函数是通过指针调用的,呈现多态性,需要在运行时期间才能确定,所以不能为内联。
  Base *ptr = new Derived();
  ptr->who();

  // 因为Base有虚析构函数(virtual ~Base() {}),所以 delete
  // 时,会先调用派生类(Derived)析构函数,再调用基类(Base)析构函数,防止内存泄漏。
  delete ptr;

  return 0;
}


================================================
FILE: basic_content/virtual/set3/static_error.cpp
================================================
/**
 * @file static_error.cpp
 * @brief 静态函数不可以声明为虚函数,同时也不能被const和volatile关键字修饰!
 * 原因如下:
 * static成员函数不属于任何类对象或类实例,所以即使给此函数加上virutal也是没有任何意义
 * 虚函数依靠vptr和vtable来处理。vptr是一个指针,在类的构造函数中创建生成,并且只能用this指针来访问它,静态成员函数没有this指针,所以无法访问vptr。
 * @author 光城
 * @version v1
 * @date 2019-07-24
 */

virtual static void fun() {}
static void fun() const {}


================================================
FILE: basic_content/virtual/set3/vir_con.cpp
================================================
/**
 * @file vir_con.cpp
 * @brief
 * 构造函数不可以声明为虚函数。同时除了inline之外,构造函数不允许使用其它任何关键字。
 *
 * 为什么构造函数不可以为虚函数?
 *
 * 尽管虚函数表vtable是在编译阶段就已经建立的,但指向虚函数表的指针vptr是在运行阶段实例化对象时才产生的。
 * 如果类含有虚函数,编译器会在构造函数中添加代码来创建vptr。
 * 问题来了,如果构造函数是虚的,那么它需要vptr来访问vtable,可这个时候vptr还没产生。
 * 因此,构造函数不可以为虚函数。
 * 我们之所以使用虚函数,是因为需要在信息不全的情况下进行多态运行。而构造函数是用来初始化实例的,实例的类型必须是明确的。
 * 因此,构造函数没有必要被声明为虚函数。
 * 尽管构造函数不可以为虚函数,但是有些场景下我们确实需要 “Virtual Copy
 * Constructor”。
 * “虚复制构造函数”的说法并不严谨,其只是一个实现了对象复制的功能的类内函数。
 * 举一个应用场景,比如剪切板功能。
 * 复制内容作为基类,但派生类可能包含文字、图片、视频等等。
 * 我们只有在程序运行的时候才知道我们需要复制的具体是什么类型的数据。
 *
 * @author 光城
 * @version v1
 * @date 2019-07-24
 */

#include <iostream>
using namespace std;

//// LIBRARY SRART
class Base {
public:
  Base() {}

  virtual // Ensures to invoke actual object destructor
      ~Base() {}

  virtual void ChangeAttributes() = 0;

  // The "Virtual Constructor"
  static Base *Create(int id);

  // The "Virtual Copy Constructor"
  virtual Base *Clone() = 0;
};

class Derived1 : public Base {
public:
  Derived1() { cout << "Derived1 created" << endl; }

  Derived1(const Derived1 &rhs) {
    cout << "Derived1 created by deep copy" << endl;
  }

  ~Derived1() { cout << "~Derived1 destroyed" << endl; }

  void ChangeAttributes() { cout << "Derived1 Attributes Changed" << endl; }

  Base *Clone() { return new Derived1(*this); }
};

class Derived2 : public Base {
public:
  Derived2() { cout << "Derived2 created" << endl; }

  Derived2(const Derived2 &rhs) {
    cout << "Derived2 created by deep copy" << endl;
  }

  ~Derived2() { cout << "~Derived2 destroyed" << endl; }

  void ChangeAttributes() { cout << "Derived2 Attributes Changed" << endl; }

  Base *Clone() { return new Derived2(*this); }
};

class Derived3 : public Base {
public:
  Derived3() { cout << "Derived3 created" << endl; }

  Derived3(const Derived3 &rhs) {
    cout << "Derived3 created by deep copy" << endl;
  }

  ~Derived3() { cout << "~Derived3 destroyed" << endl; }

  void ChangeAttributes() { cout << "Derived3 Attributes Changed" << endl; }

  Base *Clone() { return new Derived3(*this); }
};

// We can also declare "Create" outside Base.
// But is more relevant to limit it's scope to Base
Base *Base::Create(int id) {
  // Just expand the if-else ladder, if new Derived class is created
  // User need not be recompiled to create newly added class objects

  if (id == 1) {
    return new Derived1;
  } else if (id == 2) {
    return new Derived2;
  } else {
    return new Derived3;
  }
}
//// LIBRARY END

//// UTILITY SRART
class User {
public:
  User() : pBase(0) {
    // Creates any object of Base heirarchey at runtime

    int input;

    cout << "Enter ID (1, 2 or 3): ";
    cin >> input;

    while ((input != 1) && (input != 2) && (input != 3)) {
      cout << "Enter ID (1, 2 or 3 only): ";
      cin >> input;
    }

    // Create objects via the "Virtual Constructor"
    pBase = Base::Create(input);
  }

  ~User() {
    if (pBase) {
      delete pBase;
      pBase = 0;
    }
  }

  void Action() {
    // Duplicate current object
    Base *pNewBase = pBase->Clone();

    // Change its attributes
    pNewBase->ChangeAttributes();

    // Dispose the created object
    delete pNewBase;
  }

private:
  Base *pBase;
};

//// UTILITY END

//// Consumer of User (UTILITY) class
int main() {
  User *user = new User();

  user->Action();

  delete user;
}


================================================
FILE: basic_content/virtual/set3/vir_de.cpp
================================================
/**
 * @file vir_de.cpp
 * @brief 派生类的析构函数没有被调用!
 * 输出结果:
 *      Constructing base
 *      Constructing derived
 *      Destructing base
 * @author 光城
 * @version v1
 * @date 2019-07-24
 */

// CPP program without virtual destructor
// causing undefined behavior
#include <iostream>

using namespace std;

class base {
public:
  base() { cout << "Constructing base \n"; }
  ~base() { cout << "Destructing base \n"; }
};

class derived : public base {
public:
  derived() { cout << "Constructing derived \n"; }
  ~derived() { cout << "Destructing derived \n"; }
};

int main(void) {
  derived *d = new derived();
  base *b = d;
  delete b;
  return 0;
}


================================================
FILE: basic_content/virtual/set3/virtual_function.cpp
================================================
/**
 * @file virtual_function.cpp
 * @brief 虚函数可以被私有化,但有一些细节需要注意。
 * 基类指针指向继承类对象,则调用继承类对象的函数;
 * int main()必须声明为Base类的友元,否则编译失败。 编译器报错:
 * ptr无法访问私有函数。 当然,把基类声明为public,
 * 继承类为private,该问题就不存在了。----> 见另外一个例子!
 * @author 光城
 * @version v1
 * @date 2019-07-24
 */

#include <iostream>
using namespace std;

class Derived;

class Base {
private:
  virtual void fun() { cout << "Base Fun"; }
  friend int main();
};

class Derived : public Base {
public:
  void fun() { cout << "Derived Fun"; }
};

int main() {
  Base *ptr = new Derived;
  ptr->fun();
  return 0;
}


================================================
FILE: basic_content/virtual/set3/virtual_function1.cpp
================================================
#include <iostream>
using namespace std;

class Derived;

class Base {
public:
  virtual void fun() { cout << "Base Fun"; }
  //   friend int main();
};

class Derived : public Base {
private:
  void fun() { cout << "Derived Fun"; }
};

int main() {
  Base *ptr = new Derived;
  ptr->fun();
  return 0;
}


================================================
FILE: basic_content/virtual/set3/virtual_inline.cpp
================================================
/**
 * @file virtual_inline.cpp
 * @brief 通常类成员函数都会被编译器考虑是否进行内联。
 * 但通过基类指针或者引用调用的虚函数必定不能被内联。
 * 当然,实体对象调用虚函数或者静态调用时可以被内联,虚析构函数的静态调用也一定会被内联展开。
 * @author 光城
 * @version v1
 * @date 2019-07-24
 */

#include <iostream>
using namespace std;
class Base {
public:
  virtual void who() { cout << "I am Base\n"; }
};
class Derived : public Base {
public:
  void who() { cout << "I am Derived\n"; }
};

int main() {
  // note here virtual function who() is called through
  // object of the class (it will be resolved at compile
  // time) so it can be inlined.
  Base b;
  b.who();

  // Here virtual function is called through pointer,
  // so it cannot be inlined
  Base *ptr = new Derived();
  ptr->who();

  return 0;
}


================================================
FILE: basic_content/virtual/set4/BUILD
================================================
# please run `bazel run basic_content/virtual/set4:rtti`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "rtti",
    srcs = ["rtti.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/virtual/set4/rtti.cpp
================================================
/**
 * @file rtti.cpp
 * @brief
 * 在面向对象程序设计中,有时我们需要在运行时查询一个对象是否能作为某种多态类型使用。与Java的instanceof,以及C#的as、is运算符类似,C++提供了dynamic_cast函数用于动态转型。相比C风格的强制类型转换和C++
 * reinterpret_cast,dynamic_cast提供了类型安全检查,是一种基于能力查询(Capability
 * Query)的转换,所以在多态类型间进行转换更提倡采用dynamic_cast
 * @author 光城
 * @version v1
 * @date 2019-07-24
 */

// CPP program to illustrate
// Run Time Type Identification
#include <iostream>
#include <typeinfo>
using namespace std;
class B {
  virtual void fun() {}
};
class D : public B {};

int main() {
  B *b = new D; // 向上转型
  B &obj = *b;
  D *d = dynamic_cast<D *>(b); // 向下转型
  if (d != NULL)
    cout << "works" << endl;
  else
    cout << "cannot cast B* to D*";

  try {
    D &dobj = dynamic_cast<D &>(obj);
    cout << "works" << endl;
  } catch (bad_cast bc) { // ERROR
    cout << bc.what() << endl;
  }
  return 0;
}


================================================
FILE: basic_content/virtual/set4/warn_rtti.cpp
================================================
// 在使用时需要注意:被转换对象obj的类型T1必须是多态类型,即T1必须公有继承自其它类,或者T1拥有虚函数(继承或自定义)。若T1为非多态类型,使用dynamic_cast会报编译错误。

// A为非多态类型

class A {};

// B为多态类型

class B {

public:
  virtual ~B() {}
};

// D为非多态类型

class D : public A {};

// E为非多态类型

class E : private A {};

// F为多态类型

class F : private B {};


================================================
FILE: basic_content/volatile/BUILD
================================================
# please run `bazel run basic_content/volatile:noopt_vola`
# please run `bazel run basic_content/volatile:volatile`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "noopt_vola",
    srcs = ["noopt_vola.cpp"],
    copts = ["-std=c++11"]
)

cc_binary(
    name = "volatile",
    srcs = ["volatile.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/volatile/README.md
================================================
## 关于作者:

个人公众号:

![](../img/wechat.jpg)

## 1.volatile

被 `volatile` 修饰的变量,在对其进行读写操作时,会引发一些**可观测的副作用**。而这些可观测的副作用,是由**程序之外的因素决定的**。

## 2.volatile应用
(1)并行设备的硬件寄存器(如状态寄存器)。
假设要对一个设备进行初始化,此设备的某一个寄存器为0xff800000。

```c++
int  *output = (unsigned  int *)0xff800000; //定义一个IO端口;  
int   init(void)  
{  
    int i;  
    for(i=0;i< 10;i++)
    {  
    *output = i;  
    }  
}
```
经过编译器优化后,编译器认为前面循环半天都是废话,对最后的结果毫无影响,因为最终只是将output这个指针赋值为 9,所以编译器最后给你编译编译的代码结果相当于:
```c++
int  init(void)  
{  
    *output = 9;  
}
```
如果你对此外部设备进行初始化的过程是必须是像上面代码一样顺序的对其赋值,显然优化过程并不能达到目的。反之如果你不是对此端口反复写操作,而是反复读操作,其结果是一样的,编译器在优化后,也许你的代码对此地址的读操作只做了一次。然而从代码角度看是没有任何问题的。这时候就该使用volatile通知编译器这个变量是一个不稳定的,在遇到此变量时候不要优化。

(2)一个中断服务子程序中访问到的变量;

```c++
static int i=0;

int main()
{
    while(1)
    {
    if(i) dosomething();
    }
}

/* Interrupt service routine */
void IRS()
{
	i=1;
}
```
上面示例程序的本意是产生中断时,由中断服务子程序IRS响应中断,变更程序变量i,使在main函数中调用dosomething函数,但是,由于编译器判断在main函数里面没有修改过i,因此可能只执行一次对从i到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“i副本”,导致dosomething永远不会被调用。如果将变量i加上volatile修饰,则编译器保证对变量i的读写操作都不会被优化,从而保证了变量i被外部程序更改后能及时在原程序中得到感知。

(3)多线程应用中被多个任务共享的变量。
当多个线程共享某一个变量时,该变量的值会被某一个线程更改,应该用 volatile 声明。作用是防止编译器优化把变量从内存装入CPU寄存器中,当一个线程更改变量后,未及时同步到其它线程中导致程序出错。volatile的意思是让编译器每次操作该变量时一定要从内存中真正取出,而不是使用已经存在寄存器中的值。示例如下:
```c++
volatile  bool bStop=false;  //bStop 为共享全局变量  
//第一个线程
void threadFunc1()
{
    ...
    while(!bStop){...}
}
//第二个线程终止上面的线程循环
void threadFunc2()
{
    ...
    bStop = true;
}
```
要想通过第二个线程终止第一个线程循环,如果bStop不使用volatile定义,那么这个循环将是一个死循环,因为bStop已经读取到了寄存器中,寄存器中bStop的值永远不会变成FALSE,加上volatile,程序在执行时,每次均从内存中读出bStop的值,就不会死循环了。

是否了解volatile的应用场景是区分C/C++程序员和嵌入式开发程序员的有效办法,搞嵌入式的家伙们经常同硬件、中断、RTOS等等打交道,这些都要求用到volatile变量,不懂得volatile将会带来程序设计的灾难。

## 3.volatile常见问题
下面的问题可以看一下面试者是不是真正了解volatile。
(1)一个参数既可以是const还可以是volatile吗?为什么?
可以。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

(2)一个指针可以是volatile吗?为什么?
可以。尽管这并不常见。一个例子是当一个中断服务子程序修改一个指向一个buffer的指针时。

(3)下面的函数有什么错误?
```c++
int square(volatile int *ptr) 
{ 
return *ptr * *ptr; 
} 
```
这段代码有点变态,其目的是用来返回指针ptr指向值的平方,但是,由于ptr指向一个volatile型参数,编译器将产生类似下面的代码:
```c++
int square(volatile int *ptr) 
{ 
int a,b; 
a = *ptr; 
b = *ptr; 
return a * b; 
} 
```
由于*ptr的值可能被意想不到地改变,因此a和b可能是不同的。结果,这段代码可能返回的不是你所期望的平方值!正确的代码如下:
```c++
long square(volatile int *ptr) 
{ 
int a=*ptr; 
return a * a; 
} 
```
## 4.volatile使用

- volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素(操作系统、硬件、其它线程等)更改。所以使用 volatile 告诉编译器不应对这样的对象进行优化。

- volatile 关键字声明的变量,每次访问时都必须从内存中取出值(没有被 volatile 修饰的变量,可能由于编译器的优化,从 CPU 寄存器中取值)
- const 可以是 volatile (如只读的状态寄存器)
- 指针可以是 volatile

代码学习:

- [noopt_vola.cpp](./noopt_vola.cpp)
- [volatile.cpp](./volatile.cpp)



================================================
FILE: basic_content/volatile/noopt_vola.cpp
================================================
/* Compile code without optimization option */
#include <stdio.h>
int main(void) {
  const int local = 10;
  int *ptr = (int *)&local;

  printf("Initial value of local : %d \n", local);

  *ptr = 100;

  printf("Modified value of local: %d \n", local);

  return 0;
}


================================================
FILE: basic_content/volatile/volatile.cpp
================================================
/* Compile code with optimization option */
#include <stdio.h>

int main(void) {
  const volatile int local = 10;
  int *ptr = (int *)&local;

  printf("Initial value of local : %d \n", local);

  *ptr = 100;

  printf("Modified value of local: %d \n", local);

  return 0;
}


================================================
FILE: basic_content/vptr_vtable/BUILD
================================================
# please run `bazel run basic_content/vptr_vtable:vptr1`
load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "vptr1",
    srcs = ["vptr1.cpp"],
    copts = ["-std=c++11"]
)

================================================
FILE: basic_content/vptr_vtable/README.md
================================================
# 深入浅出C++虚函数的vptr与vtable

## 关于作者:

个人公众号:

![](../img/wechat.jpg)



## 1.基础理论

为了实现虚函数,C ++使用一种称为虚拟表的特殊形式的后期绑定。该虚拟表是用于解决在动态/后期绑定方式的函数调用函数的查找表。虚拟表有时会使用其他名称,例如“vtable”,“虚函数表”,“虚方法表”或“调度表”。

虚拟表实际上非常简单,虽然用文字描述有点复杂。首先,**每个使用虚函数的类(或者从使用虚函数的类派生)都有自己的虚拟表**。该表只是编译器在编译时设置的静态数组。虚拟表包含可由类的对象调用的每个虚函数的一个条目。此表中的每个条目只是一个函数指针,指向该类可访问的派生函数。

其次,编译器还会添加一个隐藏指向基类的指针,我们称之为vptr。vptr在创建类实例时自动设置,以便指向该类的虚拟表。与this指针不同,this指针实际上是编译器用来解析自引用的函数参数,vptr是一个真正的指针。

因此,它使每个类对象的分配大一个指针的大小。这也意味着vptr由派生类继承,这很重要。

## 2.实现与内部结构

下面我们来看自动与手动操纵vptr来获取地址与调用虚函数!

开始看代码之前,为了方便大家理解,这里给出调用图:

![base](./img/base.jpg)

代码全部遵循标准的注释风格,相信大家看了就会明白,不明白的话,可以留言!

```c++
/**
 * @file vptr1.cpp
 * @brief C++虚函数vptr和vtable
 * 编译:g++ -g -o vptr vptr1.cpp -std=c++11
 * @author 光城
 * @version v1
 * @date 2019-07-20
 */

#include <iostream>
#include <stdio.h>
using namespace std;

/**
 * @brief 函数指针
 */
typedef void (*Fun)();

/**
 * @brief 基类
 */
class Base
{
    public:
        Base(){};
        virtual void fun1()
        {
            cout << "Base::fun1()" << endl;
        }
        virtual void fun2()
        {
            cout << "Base::fun2()" << endl;
        }
        virtual void fun3(){}
        ~Base(){};
};

/**
 * @brief 派生类
 */
class Derived: public Base
{
    public:
        Derived(){};
        void fun1()
        {
            cout << "Derived::fun1()" << endl;
        }
        void fun2()
        {
            cout << "DerivedClass::fun2()" << endl;
        }
        ~Derived(){};
};
/**
 * @brief 获取vptr地址与func地址,vptr指向的是一块内存,这块内存存放的是虚函数地址,这块内存就是我们所说的虚表
 *
 * @param obj
 * @param offset
 *
 * @return 
 */
Fun getAddr(void* obj,unsigned int offset)
{
    cout<<"======================="<<endl;
    void* vptr_addr = (void *)*(unsigned long *)obj;  //64位操作系统,占8字节,通过*(unsigned long *)obj取出前8字节,即vptr指针
    printf("vptr_addr:%p\n",vptr_addr);
    
    /**
     * @brief 通过vptr指针访问virtual table,因为虚表中每个元素(虚函数指针)在64位编译器下是8个字节,因此通过*(unsigned long *)vptr_addr取出前8字节,
     * 后面加上偏移量就是每个函数的地址!
     */
    void* func_addr = (void *)*((unsigned long *)vptr_addr+offset);
    printf("func_addr:%p\n",func_addr);
    return (Fun)func_addr;
}
int main(void)
{
    Base ptr;
    Derived d;
    Base *pt = new Derived(); // 基类指针指向派生类实例
    Base &pp = ptr; // 基类引用指向基类实例
    Base &p = d; // 基类引用指向派生类实例
    cout<<"基类对象直接调用"<<endl;
    ptr.fun1();
    cout<<"基类引用指向基类实例"<<endl;
    pp.fun1(); 
    cout<<"基类指针指向派生类实例并调用虚函数"<<endl;
    pt->fun1();
    cout<<"基类引用指向派生类实例并调用虚函数"<<endl;
    p.fun1();
    
    // 手动查找vptr 和 vtable
    Fun f1 = getAddr(pt, 0);
    (*f1)();
    Fun f2 = getAddr(pt, 1);
    (*f2)();
    delete pt;
    return 0;
}
```

运行结果:

```
基类对象直接调用
Base::fun1()
基类引用指向基类实例
Base::fun1()
基类指针指向派生类实例并调用虚函数
Derived::fun1()
基类引用指向派生类实例并调用虚函数
Derived::fun1()
=======================
vptr_addr:0x401130
func_addr:0x400ea8
Derived::fun1()
=======================
vptr_addr:0x401130
func_addr:0x400ed4
DerivedClass::fun2()
```

我们发现C++的动态多态性是通过虚函数来实现的。简单的说,通过virtual函数,指向子类的基类指针可以调用子类的函数。例如,上述通过基类指针指向派生类实例,并调用虚函数,将上述代码简化为:

```c++
Base *pt = new Derived(); // 基类指针指向派生类实例
cout<<"基类指针指向派生类实例并调用虚函数"<<endl;
pt->fun1();
```

其过程为:首先程序识别出fun1()是个虚函数,其次程序使用pt->vptr来获取Derived的虚拟表。第三,它查找Derived虚拟表中调用哪个版本的fun1()。这里就可以发现调用的是Derived::fun1()。因此pt->fun1()被解析为Derived::fun1()!

除此之外,上述代码大家会看到,也包含了手动获取vptr地址,并调用vtable中的函数,那么我们一起来验证一下上述的地址与真正在自动调用vtable中的虚函数,比如上述`pt->fun1()`的时候,是否一致!

这里采用gdb调试,在编译的时候记得加上`-g`。

通过`gdb vptr`进入gdb调试页面,然后输入`b Derived::fun1`对fun1打断点,然后通过输入r运行程序到断点处,此时我们需要查看调用栈中的内存地址,通过`disassemable fun1`可以查看当前有关fun1中的相关汇编代码,我们看到了`0x0000000000400ea8`,然后再对比上述的结果会发现与手动调用的fun1一致,fun2类似,以此证明代码正确!

gdb调试信息如下:

```c++
(gdb) b Derived::fun1
Breakpoint 1 at 0x400eb4: file vptr1.cpp, line 23.
(gdb) r
Starting program: /home/light/Program/CPlusPlusThings/virtual/pure_virtualAndabstract_class/vptr 
基类对象直接调用
Base::fun1()
基类引用指向派生类实例
Base::fun1()
基类指针指向派生类实例并调用虚函数

Breakpoint 1, Derived::fun1 (this=0x614c20) at vptr1.cpp:23
23	            cout << "Derived::fun1()" << endl;
(gdb) disassemble fun1
Dump of assembler code for function Derived::fun1():
   0x0000000000400ea8 <+0>:	push   %rbp
   0x0000000000400ea9 <+1>:	mov    %rsp,%rbp
   0x0000000000400eac <+4>:	sub    $0x10,%rsp
   0x0000000000400eb0 <+8>:	mov    %rdi,-0x8(%rbp)
=> 0x0000000000400eb4 <+12>:	mov    $0x401013,%esi
   0x0000000000400eb9 <+17>:	mov    $0x602100,%edi
   0x0000000000400ebe <+22>:	callq  0x4009d0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
   0x0000000000400ec3 <+27>:	mov    $0x400a00,%esi
   0x0000000000400ec8 <+32>:	mov    %rax,%rdi
   0x0000000000400ecb <+35>:	callq  0x4009f0 <_ZNSolsEPFRSoS_E@plt>
   0x0000000000400ed0 <+40>:	nop
   0x0000000000400ed1 <+41>:	leaveq 
   0x0000000000400ed2 <+42>:	retq   
End of assembler dump.
(gdb) disassemble fun2
Dump of assembler code for function Derived::fun2():
   0x0000000000400ed4 <+0>:	push   %rbp
   0x0000000000400ed5 <+1>:	mov    %rsp,%rbp
   0x0000000000400ed8 <+4>:	sub    $0x10,%rsp
   0x0000000000400edc <+8>:	mov    %rdi,-0x8(%rbp)
   0x0000000000400ee0 <+12>:	mov    $0x401023,%esi
   0x0000000000400ee5 <+17>:	mov    $0x602100,%edi
   0x0000000000400eea <+22>:	callq  0x4009d0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
   0x0000000000400eef <+27>:	mov    $0x400a00,%esi
   0x0000000000400ef4 <+32>:	mov    %rax,%rdi
   0x0000000000400ef7 <+35>:	callq  0x4009f0 <_ZNSolsEPFRSoS_E@plt>
   0x0000000000400efc <+40>:	nop
   0x0000000000400efd <+41>:	leaveq 
   0x0000000000400efe <+42>:	retq   
End of assembler dump.
```



================================================
FILE: basic_content/vptr_vtable/vptr1.cpp
================================================
#include <iostream>
#include <stdio.h>
using namespace std;

/**
 * @brief 函数指针
 */
typedef void (*Fun)();

/**
 * @brief 基类
 */
class Base {
public:
  Base(){};
  virtual void fun1() { cout << "Base::fun1()" << endl; }
  virtual void fun2() { cout << "Base::fun2()" << endl; }
  virtual void fun3() {}
  ~Base(){};
};

/**
 * @brief 派生类
 */
class Derived : public Base {
public:
  Derived(){};
  void fun1() { cout << "Derived::fun1()" << endl; }
  void fun2() { cout << "DerivedClass::fun2()" << endl; }
  ~Derived(){};
};

/**
 * @brief
 * 获取vptr地址与func地址,vptr指向的是一块内存,这块内存存放的是虚函数地址,这块内存就是我们所说的虚表
 *
 * @param obj
 * @param offset
 *
 * @return
 */
Fun getAddr(void *obj, unsigned int offset) {
  cout << "=======================" << endl;
  void *vptr_addr =
      (void *)*(unsigned long *)obj; // 64位操作系统,占8字节,通过*(unsigned
                                     // long *)obj取出前8字节,即vptr指针
  printf("vptr_addr:%p\n", vptr_addr);

  /**
   * @brief 通过vptr指针访问virtual
   * table,因为虚表中每个元素(虚函数指针)在64位编译器下是8个字节,因此通过*(unsigned
   * long *)vptr_addr取出前8字节, 后面加上偏移量就是每个函数的地址!
   */
  void *func_addr = (void *)*((unsigned long *)vptr_addr + offset);
  printf("func_addr:%p\n", func_addr);
  return (Fun)func_addr;
}
int main(void) {
  Base ptr;
  Derived d;
  Base *pt = new Derived(); // 基类指针指向派生类实例
  Base &pp = ptr;           // 基类引用指向基类实例
  Base &p = d;              // 基类引用指向派生类实例
  cout << "基类对象直接调用" << endl;
  ptr.fun1();
  cout << "基类引用指向基类实例" << endl;
  pp.fun1();
  cout << "基类指针指向派生类实例并调用虚函数" << endl;
  pt->fun1();
  cout << "基类引用指向派生类实例并调用虚函数" << endl;
  p.fun1();

  // 手动查找vptr 和 vtable
  Fun f1 = getAddr(pt, 0);
  (*f1)();
  Fun f2 = getAddr(pt, 1);
  (*f2)();

  delete pt;
  return 0;
}


================================================
FILE: codingStyleIdioms/1_classInitializers/1.1_nest.cpp
================================================
/* 1.1_类之间嵌套.cpp */
//
// Created by light on 19-12-9.
//

#include <iostream>

class Animal {
public:
    Animal() {
        std::cout << "Animal() is called" << std::endl;
    }

    Animal(const Animal &) {
        std::cout << "Animal (const Animal &) is called" << std::endl;
    }

    Animal &operator=(const Animal &) {
        std::cout << "Animal & operator=(const Animal &) is called" << std::endl;
        return *this;
    }

    ~Animal() {
        std::cout << "~Animal() is called" << std::endl;
    }
};

class Dog {
public:
    // 第一种: 使用初始化列表。
    Dog(const Animal &animal) : __animal(animal) {
        std::cout << "Dog(const Animal &animal) is called" << std::endl;
    }
    // 第二种:构造函数赋值来初始化对象。
//    Dog(const Animal &animal) {
//        __animal = animal;
//        std::cout << "Dog(const Animal &animal) is called" << std::endl;
//    }
    ~Dog() {
        std::cout << "~Dog() is called" << std::endl;
    }

private:
    Animal __animal;
};

int main() {
    Animal animal;
    std::cout << std::endl;
    Dog d(animal);
    std::cout << std::endl;
    return 0;
}

================================================
FILE: codingStyleIdioms/1_classInitializers/1.2_nodefault_ctor.cpp
================================================
/* 1.2_无默认构造的继承.cpp */
//
// Created by light on 19-12-9.
//
#include <iostream>
class Animal {
public:
    Animal(int age) {
        std::cout << "Animal(int age) is called" << std::endl;
    }

    Animal(const Animal & animal) {
        std::cout << "Animal (const Animal &) is called" << std::endl;
    }

    Animal &operator=(const Animal & amimal) {
        std::cout << "Animal & operator=(const Animal &) is called" << std::endl;
        return *this;
    }

    ~Animal() {
        std::cout << "~Animal() is called" << std::endl;
    }

};

class Dog : Animal {
public:
    Dog(int age) : Animal(age) {
        std::cout << "Dog(int age) is called" << std::endl;
    }

    ~Dog() {
        std::cout << "~Dog() is called" << std::endl;
    }
};

int main() {
    Animal animal(10);
    std::cout << std::endl;
    Dog d(100);
    std::cout << std::endl;
    return 0;
}

================================================
FILE: codingStyleIdioms/1_classInitializers/1.3_const.cpp
================================================
/* 1.3_类中const数据成员、引用数据成员.cpp */
//
// Created by light on 19-12-9.
//

#include <iostream>

class Animal {
public:
    Animal(int& age,std::string name):age_(age),name_(name) {
        std::cout << "Animal(int age) is called" << std::endl;
    }
private:
    int &age_;
    const std::string name_;
};

int main() {
    int x = 10;
    Animal animal(x,"hh");
    return 0;
}

================================================
FILE: codingStyleIdioms/1_classInitializers/BUILD
================================================
# please run `bazel run //codingStyleIdioms/1_classInitializers:1.2_nodefault_ctor`
# please run `bazel run //codingStyleIdioms/1_classInitializers:initializer`
# please run `bazel run //codingStyleIdioms/1_classInitializers:1.1_nest`
# please run `bazel run //codingStyleIdioms/1_classInitializers:1.3_const`

load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "1.2_nodefault_ctor",
    srcs = ["1.2_nodefault_ctor.cpp"],
    copts = ["-std=c++11"],
)
cc_binary(
    name = "initializer",
    srcs = ["initializer.cpp"],
    copts = ["-std=c++11"],
)
cc_binary(
    name = "1.1_nest",
    srcs = ["1.1_nest.cpp"],
    copts = ["-std=c++11"],
)
cc_binary(
    name = "1.3_const",
    srcs = ["1.3_const.cpp"],
    copts = ["-std=c++11"],
)


================================================
FILE: codingStyleIdioms/1_classInitializers/README.md
================================================
# 初始化列表与赋值

- const成员的初始化只能在构造函数初始化列表中进行
- 引用成员的初始化也只能在构造函数初始化列表中进行
- 对象成员(对象成员所对应的类没有默认构造函数)的初始化,也只能在构造函数初始化列表中进行

## 类之间嵌套

**第一种: 使用初始化列表。**


```cpp
class Animal {
public:
    Animal() {
        std::cout << "Animal() is called" << std::endl;
    }

    Animal(const Animal &) {
        std::cout << "Animal (const Animal &) is called" << std::endl;
    }

    Animal &operator=(const Animal &) {
        std::cout << "Animal & operator=(const Animal &) is called" << std::endl;
        return *this;
    }

    ~Animal() {
        std::cout << "~Animal() is called" << std::endl;
    }
};

class Dog {
public:
    Dog(const Animal &animal) : __animal(animal) {
        std::cout << "Dog(const Animal &animal) is called" << std::endl;
    }

    ~Dog() {
        std::cout << "~Dog() is called" << std::endl;
    }

private:
    Animal __animal;
};

int main() {
    Animal animal;
    std::cout << std::endl;
    Dog d(animal);
    std::cout << std::endl;
    return 0;
}
```

运行结果:
```cpp
Animal() is called

Animal (const Animal &) is called
Dog(const Animal &animal) is called

~Dog() is called
~Animal() is called
~Animal() is called
```

依次分析从上到下:

main函数中`Animal animal;`调用默认构造。

`Dog d(animal);`等价于:

```
Animal __animal = animal;
```
实际上就是调用了拷贝构造,因此输出了:
```
Animal (const Animal &) is called
```
再然后打印Dog的构造函数里面的输出。

最后调用析构,程序结束。

**第二种:构造函数赋值来初始化对象。**

构造函数修改如下:
```cpp
Dog(const Animal &animal) {
    __animal = animal;
    std::cout << "Dog(const Animal &animal) is called" << std::endl;
}
```
此时输出结果:
```
Animal() is called

Animal() is called
Animal & operator=(const Animal &) is called
Dog(const Animal &animal) is called

~Dog() is called
~Animal() is called
~Animal() is called
```

于是得出:

当调用`Dog d(animal);`时,等价于:

先定义对象,再进行赋值,因此先调用了默认构造,再调用=操作符重载函数。

```cpp
// 假设之前已经有了animal对象
Animal __animal;
__animal = animal;
```

> 小结

通过上述我们得出如下结论:

- **类中包含其他自定义的class或者struct,采用初始化列表,实际上就是创建对象同时并初始化**
- **而采用类中赋值方式,等价于先定义对象,再进行赋值,一般会先调用默认构造,在调用=操作符重载函数。**

## 无默认构造函数的继承关系中

现考虑把上述的关系改为继承,并修改Animal与Dog的构造函数,如下代码:

```cpp
class Animal {
public:
    Animal(int age) {
        std::cout << "Animal(int age) is called" << std::endl;
    }

    Animal(const Animal & animal) {
        std::cout << "Animal (const Animal &) is called" << std::endl;
    }

    Animal &operator=(const Animal & amimal) {
        std::cout << "Animal & operator=(const Animal &) is called" << std::endl;
        return *this;
    }

    ~Animal() {
        std::cout << "~Animal() is called" << std::endl;
    }
};

class Dog : Animal {
public:
    Dog(int age) : Animal(age) {
        std::cout << "Dog(int age) is called" << std::endl;
    }

    ~Dog() {
        std::cout << "~Dog() is called" << std::endl;
    }

};
```

上述是通过初始化列表给基类带参构造传递参数,如果不通过初始化列表传递,会发生什么影响?

去掉初始化列表
```
Dog(int age)  {
    std::cout << "Dog(int age) is called" << std::endl;
}
```
运行程序:

```
error: no matching function for call to ‘Animal::Animal()’
```

由于在Animal中没有默认构造函数,所以报错,遇到这种问题属于灾难性的,我们应该尽量避免,可以通过初始化列表给基类的构造初始化。


## 类中const数据成员、引用数据成员

特别是引用数据成员,必须用初始化列表初始化,而不能通过赋值初始化!

例如:在上述的Animal中添加私有成员,并修改构造函数:
```cpp
class Animal {
public:
    Animal(int age,std::string name) {
        std::cout << "Animal(int age) is called" << std::endl;
    }
private:
    int &age_;
    const std::string name_;
};
```

报下面错误:

```cpp
error: uninitialized reference member in ‘int&’
```

应该改为下面:

```cpp
Animal(int age, std::string name) : age_(age), name_(name) {
    std::cout << "Animal(int age) is called" << std::endl;
}
```



================================================
FILE: codingStyleIdioms/1_classInitializers/initializer.cpp
================================================
/* initializer.cpp */
//
// Created by light on 19-12-9.
//

#include <iostream>

using namespace std;

class A {
public:
    A(int a) : _a(a), _p(nullptr) {     // 初始化列表

    }

private:
    int _a;
    int *_p;
};

int main() {
    A aa(10);
    return 0;
}


================================================
FILE: codingStyleIdioms/2_enumclass/BUILD
================================================
# please run `bazel run //codingStyleIdioms/2_enumclass:namespace`

load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "namespace",
    srcs = ["namespace.cpp"],
    copts = ["-std=c++11"],
)


================================================
FILE: codingStyleIdioms/2_enumclass/README.md
================================================
# C++惯用法之enum class

在Effective modern C++中Item 10: Prefer scoped enums to unscoped enum,调到要用有范围的enum class代替无范围的enum。

例如:

```cpp
enum Shape {circle,retangle};
auto circle = 10;  // error
```

上述错误是因为两个circle在同一范围。
对于enum等价于:
```cpp
#define circle 0
#define retangle 1
```
因此后面再去定义circle就会出错。

所以不管枚举名是否一样,里面的成员只要有一致的,就会出问题。
例如:
```cpp
enum A {a,b};
enum B {c,a};
```
a出现两次,在enum B的a处报错。

根据前面我们知道,enum名在范围方面没有什么作用,因此我们想到了namespace,如下例子:
```cpp
// 在创建枚举时,将它们放在名称空间中,以便可以使用有意义的名称访问它们:
namespace EntityType {
    enum Enum {
        Ground = 0,
        Human,
        Aerial,
        Total
    };
}

void foo(EntityType::Enum entityType)
{
    if (entityType == EntityType::Ground) {
        /*code*/
    }
}
```
将命名空间起的有意思点,就可以达到想要的效果。

但是不断的使用命名空间,势必太繁琐,而且如果我不想使用namespace,要达到这样的效果,便会变得不安全,也没有约束。

因此在c++11后,引入enum class。

enum class 解决了为enum成员定义类型、类型安全、约束等问题。
回到上述例子:
```cpp
// enum class
enum class EntityType {
    Ground = 0,
    Human,
    Aerial,
    Total
};

void foo(EntityType entityType)
{
    if (entityType == EntityType::Ground) {
        /*code*/
    }
}
```
这便是这一节要阐述的惯用法:enum class。

================================================
FILE: codingStyleIdioms/2_enumclass/namespace.cpp
================================================
//
// Created by light on 19-12-9.
//

#include <iostream>

using namespace std;
// 在创建枚举时,将它们放在名称空间中,以便可以使用有意义的名称访问它们:
namespace EntityType {
    enum Enum {
        Ground = 0,
        Human,
        Aerial,
        Total
    };
}

void foo(EntityType::Enum entityType)
{
    if (entityType == EntityType::Ground) {
        /*code*/
    }
}

// enum class
enum class EntityType1 {
    Ground = 0,
    Human,
    Aerial,
    Total
};

void foo(EntityType1 entityType)
{
    if (entityType == EntityType1::Ground) {
        /*code*/
    }
}

int main() {

    return 0;
}


================================================
FILE: codingStyleIdioms/3_RAII/BUILD
================================================
# please run `bazel run //codingStyleIdioms/3_RAII:RAII_fstram`
# please run `bazel run //codingStyleIdioms/3_RAII:c++_example1`
# please run `bazel run //codingStyleIdioms/3_RAII:c++_example`
# please run `bazel run //codingStyleIdioms/3_RAII:RAII`
# please run `bazel run //codingStyleIdioms/3_RAII:c_example`
# please run `bazel run //codingStyleIdioms/3_RAII:c++_example2`

load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "RAII_fstram",
    srcs = ["RAII_fstram.cpp"],
    copts = ["-std=c++11"],
)
cc_binary(
    name = "c++_example1",
    srcs = ["c++_example1.cpp"],
    copts = ["-std=c++11"],
)
cc_binary(
    name = "c++_example",
    srcs = ["c++_example.cpp"],
    copts = ["-std=c++11"],
)
cc_binary(
    name = "RAII",
    srcs = ["RAII.cpp"],
    copts = ["-std=c++11"],
)
cc_binary(
    name = "c_example",
    srcs = ["c_example.cpp"],
    copts = ["-std=c++11"],
)
cc_binary(
    name = "c++_example2",
    srcs = ["c++_example2.cpp"],
    copts = ["-std=c++11"],
)


================================================
FILE: codingStyleIdioms/3_RAII/RAII.cpp
================================================
#include <iostream>
#include <mutex>
#include <fstream>
using namespace std;
// RAII 资源获取即初始化,例1

enum class shape_type {
    circle,
    triangle,
    rectangle,
};


class shape {
public:
    shape() { cout << "shape" << endl; }

    virtual void print() {
        cout << "I am shape" << endl;
    }

    virtual ~shape() {}
};

class circle : public shape {
public:
    circle() { cout << "circle" << endl; }

    void print() {
        cout << "I am circle" << endl;
    }
};

class triangle : public shape {
public:
    triangle() { cout << "triangle" << endl; }

    void print() {
        cout << "I am triangle" << endl;
    }
};

class rectangle : public shape {
public:
    rectangle() { cout << "rectangle" << endl; }

    void print() {
        cout << "I am rectangle" << endl;
    }
};

// 利用多态 上转 如果返回值为shape,会存在对象切片问题。
shape *create_shape(shape_type type) {
    switch (type) {
        case shape_type::circle:
            return new circle();
        case shape_type::triangle:
            return new triangle();
        case shape_type::rectangle:
            return new rectangle();
    }
}

class shape_wrapper {
public:
    explicit shape_wrapper(shape *ptr = nullptr) : ptr_(ptr) {}

    ~shape_wrapper() {
        delete ptr_;
    }

    shape *get() const {
        return ptr_;
    }

private:
    shape *ptr_;
};


void foo() {
    shape_wrapper ptr(create_shape(shape_type::circle));
    ptr.get()->print();
}

int main() {

    // 第一种方式
    shape *sp = create_shape(shape_type::circle);
    sp->print();
    delete sp;

    // 第二种方式 RAII
    foo();

    return 0;
}


================================================
FILE: codingStyleIdioms/3_RAII/RAII.md
================================================
# C++惯用法之消除垃圾收集器-资源获取即初始化方法(RAII)

## 0.导语

在C语言中,有三种类型的内存分配:静态、自动和动态。静态变量是嵌入在源文件中的常数,因为它们有已知的大小并且从不改变,所以它们并不那么有趣。自动分配可以被认为是堆栈分配——当一个词法块进入时分配空间,当该块退出时释放空间。它最重要的特征与此直接相关。在C99之前,自动分配的变量需要在编译时知道它们的大小。这意味着任何字符串、列表、映射以及从这些派生的任何结构都必须存在于堆中的动态内存中。

程序员使用四个基本操作明确地分配和释放动态内存:malloc、realloc、calloc和free。前两个不执行任何初始化,内存可能包含碎片。除了自由,他们都可能失败。在这种情况下,它们返回一个空指针,其访问是未定义的行为;在最好的情况下,你的程序会崩溃。在最坏的情况下,你的程序看起来会工作一段时间,在崩溃前处理垃圾数据。

例如:	

```cpp
int main() {
   char *str = (char *) malloc(7); 
   strcpy(str, "toptal");
   printf("char array = \"%s\" @ %u\n", str, str);

   str = (char *) realloc(str, 11);
   strcat(str, ".com");
   printf("char array = \"%s\" @ %u\n", str, str);

   free(str);
   
   return(0);
}
```

输出:

```cpp
char array = "toptal" @ 2762894960
char array = "toptal.com" @ 2762894960
```

尽管代码很简单,但它已经包含了一个反模式和一个有问题的决定。在现实生活中,你不应该直接写字节数,而应该使用sizeof函数。类似地,我们将char *数组精确地分配给我们需要的字符串大小的两倍(比字符串长度多一倍,以说明空终止),这是一个相当昂贵的操作。一个更复杂的程序可能会构建一个更大的字符串缓冲区,允许字符串大小增长。

## 1.RAII的发明:新希望

至少可以说,所有手动管理都是令人不快的。 在80年代中期,Bjarne Stroustrup为他的全新语言C ++发明了一种新的范例。 他将其称为“资源获取就是初始化”,其基本见解如下:**可以指定对象具有构造函数和析构函数,这些构造函数和析构函数在适当的时候由编译器自动调用,这为管理给定对象的内存提供了更为方便的方法。** 需要,并且该技术对于不是内存的资源也很有用。

意味着上面的例子在c++中更简洁:

```cpp
int main() {
   std::string str = std::string ("toptal");
   std::cout << "string object: " << str << " @ " << &str << "\n";
   
   str += ".com";
   std::cout << "string object: " << str << " @ " << &str << "\n";
   
   return(0);
}
```

输出:

```cpp
string object: toptal @ 0x7fffa67b9400
string object: toptal.com @ 0x7fffa67b9400
```

在上述例子中,我们没有手动内存管理!构造string对象,调用重载方法,并在函数退出时自动销毁。不幸的是,同样的简单也会导致其他问题。让我们详细地看一个例子:

```cpp
vector<string> read_lines_from_file(string &file_name) {
	vector<string> lines;
	string line;
	
	ifstream file_handle (file_name.c_str());
	while (file_handle.good() && !file_handle.eof() && file_handle.peek()!=EOF) {
		getline(file_handle, line);
		lines.push_back(line);
	}
	
	file_handle.close();
	
	return lines;
}

int main(int argc, char* argv[]) {
	// get file name from the first argument
	string file_name (argv[1]);
	int count = read_lines_from_file(file_name).size();
	cout << "File " << file_name << " contains " << count << " lines.";
	
	return 0;
}
```

输出:

```cpp
File makefile contains 37 lines.
```

这看起来很简单。`vector`被填满、返回和调用。然而,作为关心性能的高效程序员,这方面的一些问题困扰着我们:在return语句中,由于使用了值语义,`vector`在销毁之前不久就被复制到一个新`vector`中。

> 在现代C ++中,这不再是严格的要求了。 C ++ 11引入了移动语义的概念,其中将原点保留在有效状态(以便仍然可以正确销毁)但未指定状态。 对于编译器而言,返回调用是最容易优化以优化语义移动的情况,因为它知道在进行任何进一步访问之前不久将销毁源。 但是,该示例的目的是说明为什么人们在80年代末和90年代初发明了一大堆垃圾收集的语言,而在那个时候C ++ move语义不可用。

对于数据量比较大的文件,这可能会变得昂贵。 让我们对其进行优化,只返回一个指针。 语法进行了一些更改,但其他代码相同:

```cpp
vector<string> * read_lines_from_file(string &file_name) {
	vector<string> * lines;
	string line;
	
	ifstream file_handle (file_name.c_str());
	while (file_handle.good() && !file_handle.eof() && file_handle.peek()!=EOF) {
		getline(file_handle, line);
		lines->push_back(line);
	}
	
	file_handle.close();
	
	return lines;
}
int main(int argc, char* argv[]) {
	// get file name from the first argument
	string file_name (argv[1]);
	int count = read_lines_from_file(file_name).size();
	cout << "File " << file_name << " contains " << count << " lines.";
	
	return 0;
}
```

输出:

```
Segmentation fault (core dumped)
```

程序崩溃!我们只需要将上述的`lines`进行内存分配:

```cpp
vector<string> * lines = new vector<string>;
```

这样就可以运行了!

不幸的是,尽管这看起来很完美,但它仍然有一个缺陷:它会泄露内存。在C++中,指向堆的指针在不再需要后必须手动删除;否则,一旦最后一个指针超出范围,该内存将变得不可用,并且直到进程结束时操作系统对其进行管理后才会恢复。惯用的现代C++将在这里使用`unique_ptr`,它实现了期望的行为。它删除指针超出范围时指向的对象。然而,这种行为直到C++11才成为语言的一部分。

在这里,可以直接使用C++11之前的语法,只是把main中改一下即可:

```cpp
vector<string> * read_lines_from_file(string &file_name) {
	vector<string> * lines = new vector<string>;
	string line;
	
	ifstream file_handle (file_name.c_str());
	while (file_handle.good() && !file_handle.eof() && file_handle.peek()!=EOF) {
		getline(file_handle, line);
		lines->push_back(line);
	}
	
	file_handle.close();
	
	return lines;
}

int main(int argc, char* argv[]) {
	// get file name from the first argument
	string file_name (argv[1]);
	vector<string> * file_lines = read_lines_from_file(file_name);
	int count = file_lines->size();
	delete file_lines;
	cout << "File " << file_name << " contains " << count << " lines.";
	
	return 0;
}
```

手动去分配内存与释放内存。

**不幸的是,随着程序扩展到上述范围之外,很快就变得更加难以推理指针应该在何时何地被删除。当一个函数返回指针时,你现在拥有它吗?您应该在完成后自己删除它,还是它属于某个稍后将被一次性释放的数据结构?一方面出错,内存泄漏,另一方面出错,你已经破坏了正在讨论的数据结构和其他可能的数据结构,因为它们试图取消引用现在不再有效的指针。**

## 2.“使用垃圾收集器,flyboy!”

垃圾收集器不是一项新技术。 它们由John McCarthy在1959年为Lisp发明。 1980年,随着Smalltalk-80的出现,垃圾收集开始成为主流。 但是,1990年代代表了该技术的真正发芽:在1990年至2000年之间,发布了多种语言,所有语言都使用一种或另一种垃圾回收:Haskell,Python,Lua,Java,JavaScript,Ruby,OCaml 和C#是最著名的。

什么是垃圾收集? 简而言之,这是一组用于自动执行手动内存管理的技术。 它通常作为具有手动内存管理的语言(例如C和C ++)的库提供,但在需要它的语言中更常用。 最大的优点是程序员根本不需要考虑内存。 都被抽象了。 例如,相当于我们上面的文件读取代码的Python就是这样:

```python
def read_lines_from_file(file_name):
	lines = []
	with open(file_name) as fp: 
		for line in fp:
			lines.append(line)
	return lines
	
if __name__ == '__main__':
	import sys
	file_name = sys.argv[1]
	count = len(read_lines_from_file(file_name))
	print("File {} contains {} lines.".format(file_name, count))
```

行数组是在第一次分配给它时出现的,并且不复制到调用范围就返回。 由于时间不确定,它会在超出该范围后的某个时间被垃圾收集器清理。 有趣的是,在Python中,用于非内存资源的RAII不是惯用语言。 允许-我们可以简单地编写`fp = open(file_name)`而不是使用with块,然后让GC清理。 但是建议的模式是在可能的情况下使用上下文管理器,以便可以在确定的时间释放它们。

尽管简化了内存管理,但要付出很大的代价。 在引用计数垃圾回收中,所有变量赋值和作用域出口都会获得少量成本来更新引用。 在标记清除系统中,在GC清除内存的同时,所有程序的执行都以不可预测的时间间隔暂停。 这通常称为世界停止事件。 同时使用这两种系统的Python之类的实现都会受到两种惩罚。 这些问题降低了垃圾收集语言在性能至关重要或需要实时应用程序的情况下的适用性。 即使在以下玩具程序上,也可以看到实际的性能下降:

```cpp
$ make cpp && time ./c++ makefile
g++ -o c++ c++.cpp
File makefile contains 38 lines.
real    0m0.016s
user    0m0.000s
sys     0m0.015s

$ time python3 python3.py makefile
File makefile contains 38 lines.

real    0m0.041s
user    0m0.015s
sys     0m0.015s
```

Python版本的实时时间几乎是C ++版本的三倍。 尽管并非所有这些差异都可以归因于垃圾收集,但它仍然是可观的。

## 3.所有权:RAII觉醒

我们知道对象的生存期由其范围决定。 但是,有时我们需要创建一个对象,该对象与创建对象的作用域无关,这是有用的,或者很有用。 在C ++中,运算符new用于创建这样的对象。 为了销毁对象,可以使用运算符delete。 由new操作员创建的对象是动态分配的,即在动态内存(也称为堆或空闲存储)中分配。 因此,由new创建的对象将继续存在,直到使用delete将其明确销毁为止。

使用new和delete时可能发生的一些错误是:

- 对象(或内存)泄漏:使用new分配对象,而忘记删除该对象。

- 过早删除(或悬挂引用):持有指向对象的另一个指针,删除该对象,然而还有其他指针在引用它。

- 双重删除:尝试两次删除一个对象。

通常,范围变量是首选。 但是,RAII可以用作new和delete的替代方法,以使对象独立于其范围而存在。 这种技术包括将指针分配到在堆上分配的对象,并将其放在句柄/管理器对象中。 后者具有一个析构函数,将负责销毁该对象。 这将确保该对象可用于任何想要访问它的函数,并且该对象在句柄对象的生存期结束时将被销毁,而无需进行显式清理。

来自C ++标准库的使用RAII的示例为std :: string和std :: vector。

考虑这段代码:

```cpp
void fn(const std::string& str)
{
    std::vector<char> vec;
    for (auto c : str)
        vec.push_back(c);
    // do something
}
```

当创建`vector`,并将元素推入`vector`时,您不必担心分配和取消分配此类元素内存。 `vector`使用new为其堆上的元素分配空间,并使用delete释放该空间。 作为vector的用户,您无需关心实现细节,并且会相信vector不会泄漏。 在这种情况下,向量是其元素的句柄对象。

标准库中使用RAII的其他示例是std :: shared_ptr,std :: unique_ptr和std :: lock_guard。

该技术的另一个名称是SBRM,是范围绑定资源管理的缩写。

现在,我们将上述读取文件例子,进行修改:

```cpp
#include <iostream>
#include <vector>
#include <cstring>
#include <fstream>
#include <bits/unique_ptr.h>

using namespace std;
unique_ptr<vector<string>> read_lines_from_file(string &file_name) {
    unique_ptr<vector<string>> lines(new vector<string>);
    string line;

    ifstream file_handle (file_name.c_str());
    while (file_handle.good() && !file_handle.eof() && file_handle.peek()!=EOF) {
        getline(file_handle, line);
        lines->push_back(line);
    }

    file_handle.close();

    return lines;
}
int main(int argc, char* argv[]) {
	// get file name from the first argument
	string file_name (argv[1]);
	int count = read_lines_from_file(file_name).get()->size();
    cout << "File " << file_name << " contains " << count << " lines.";

	return 0;
}
```

## 4.只有在最后,你才意识到RAII的真正力量。

自从编译器发明以来,手动内存管理是程序员一直在想办法避免的噩梦。 RAII是一种很有前途的模式,但由于没有一些奇怪的解决方法,它根本无法用于堆分配的对象,因此在C ++中会受到影响。 因此,在90年代出现了垃圾收集语言的爆炸式增长,旨在使程序员生活更加愉快,即使以性能为代价。

最后,RAII总结如下:

- 资源在析构函数中被释放

- 该类的实例是堆栈分配的
- 资源是在构造函数中获取的。 

RAII代表“资源获取是初始化”。

常见的例子有:

- 文件操作

- 智能指针

- 互斥量

## 5.参考文章

> 1.https://www.toptal.com/software/eliminating-garbage-collector#remote-developer-job

> 2.https://stackoverflow.com/questions/2321511/what-is-meant-by-resource-acquisition-is-initialization-raii


================================================
FILE: codingStyleIdioms/3_RAII/RAII_fstram.cpp
================================================
//
// Created by light on 19-12-9.
//
#include <iostream>
#include <fstream>

// RAII 资源获取即初始化,例2

// C ++保证在对象超出范围时调用析构函数,而不管控制如何离开该范围。
// 即使抛出异常,所有本地对象也会超出范围,因此它们的相关资源将被清除。

void foo() {
    std::fstream file("bar.txt"); // open a file "bar.txt"
    if (rand() % 2) {
        // if this exception is thrown, we leave the function, and so
        // file's destructor is called, which closes the file handle.
        throw std::exception();
    }
    // if the exception is not called, we leave the function normally, and so
    // again, file's destructor is called, which closes the file handle.
}

int main() {
    try {
        foo();
    } catch (std::exception) {
        puts("exception!");
    }
}

================================================
FILE: codingStyleIdioms/3_RAII/c++_example.cpp
================================================
//
// Created by light on 19-12-12.
//
#include <iostream>
int main() {
    std::string str = std::string ("toptal");
    std::cout << "string object: " << str << " @ " << &str << "\n";

    str += ".com";
    std::cout << "string object: " << str << " @ " << &str << "\n";

    return(0);
}

================================================
FILE: codingStyleIdioms/3_RAII/c++_example1.cpp
================================================
//
// Created by light on 19-12-12.
//
#include <iostream>
#include <vector>
#include <cstring>
#include <fstream>

using namespace std;
vector<string> read_lines_from_file(string &file_name) {
    vector<string> lines;
    string line;

    ifstream file_handle (file_name.c_str());
    //  file_handle.peek()!=EOF 解决多读一行问题
    while (file_handle.good() && !file_handle.eof() && file_handle.peek()!=EOF) {
        getline(file_handle, line);
        lines.push_back(line);
    }

    file_handle.close();

    return lines;
}
vector<string> * read_lines_from_file1(string &file_name) {
    vector<string> * lines;
    string line;

    ifstream file_handle (file_name.c_str());
    //  file_handle.peek()!=EOF
    while (file_handle.good() && !file_handle.eof() && file_handle.peek()!=EOF) {
        getline(file_handle, line);
        lines->push_back(line);
    }

    file_handle.close();

    return lines;
}
vector<string> * read_lines_from_file1_1(string &file_name) {
    vector<string> * lines=new vector<string>;
    string line;

    ifstream file_handle (file_name.c_str());
    while (file_handle.good() && !file_handle.eof() &&  file_handle.peek()!=EOF) {
        getline(file_handle, line);
        lines->push_back(line);
    }

    file_handle.close();

    return lines;
}
int main() {
    // get file name from the first argument
    string file_name ("/home/light/CLionProjects/Morden_C++/CMakeLists.txt");
    int count = read_lines_from_file(file_name).size();
    cout << "File " << file_name << " contains " << count << " lines.";

    cout<<endl;
//    string file_name1 ("/home/light/CLionProjects/Morden_C++/CMakeLists.txt");
//    int count1 = read_lines_from_file1(file_name1)->size();
//    cout << "File " << file_name << " contains " << count1 << " lines.";
    string file_name1 ("/home/light/CLionProjects/Morden_C++/CMakeLists.txt");
    int count1 = read_lines_from_file1_1(file_name1)->size();
    cout << "File " << file_name << " contains " << count1 << " lines.";
    return 0;
}


================================================
FILE: codingStyleIdioms/3_RAII/c++_example2.cpp
================================================
//
// Created by light on 19-12-12.
//
#include <iostream>
#include <vector>
#include <cstring>
#include <fstream>
#include <bits/unique_ptr.h>

using namespace std;
unique_ptr<vector<string>> read_lines_from_file(string &file_name) {
    unique_ptr<vector<string>> lines(new vector<string>);
    string line;

    ifstream file_handle (file_name.c_str());
    while (file_handle.good() && !file_handle.eof()) {
        getline(file_handle, line);
        lines->push_back(line);
    }

    file_handle.close();

    return lines;
}
int main() {
    // get file name from the first argument
    string file_name ("/home/light/CLionProjects/Morden_C++/CMakeLists.txt");
    int count = read_lines_from_file(file_name).get()->size();
    cout << "File " << file_name << " contains " << count << " lines.";
    cout<<endl;
    return 0;
}

================================================
FILE: codingStyleIdioms/3_RAII/c_example.cpp
================================================
//
// Created by light on 19-12-12.
//
#include <stdio.h>
#include <string.h>
#include <malloc.h>
int main() {
    char *str = (char *) malloc(7);
    strcpy(str, "toptal");
    printf("char array = \"%s\" @ %u\n", str, str);

    str = (char *) realloc(str, 11);
    strcat(str, ".com");
    printf("char array = \"%s\" @ %u\n", str, str);

    free(str);

    return(0);
}

================================================
FILE: codingStyleIdioms/4_copy-swap/BUILD
================================================
# please run `bazel run //codingStyleIdioms/4_copy-swap:copy-swapAndADL`

load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "copy-swapAndADL",
    srcs = ["copy-swapAndADL.cpp"],
    copts = ["-std=c++11"],
)


================================================
FILE: codingStyleIdioms/4_copy-swap/README.md
================================================
> 为什么我们需要复制和交换习惯?

任何管理资源的类(包装程序,如智能指针)都需要实现big three。尽管拷贝构造函数和析构函数的目标和实现很简单。

但是复制分配运算符无疑是最细微和最困难的。

> 应该怎么做?需要避免什么陷阱?

copy-swap是解决方案,可以很好地协助赋值运算符实现两件事:避免代码重复,并提供强大的**异常保证**。

>它是如何工作的?

**从概念上讲,它通过使用拷贝构造函数的功能来创建数据的本地副本,然后使用交换功能获取复制的数据,将旧数据与新数据交换来工作。然后,临时副本将销毁,并随身携带旧数据。我们剩下的是新数据的副本。**

为了使用copy-swap,我们需要三件事:

- 一个有效的拷贝构造函数
- 一个有效的析构函数(两者都是任何包装程序的基础,因此无论如何都应完整)以及交换功能。

交换函数是一种不抛异常函数,它交换一个类的两个对象或者成员。我们可能很想使用std :: swap而不是提供我们自己的方法,但这是不可能的。 std :: swap在实现中使用了copy-constructor和copy-assignment运算符,我们最终将尝试根据自身定义赋值运算符!

(不仅如此,对swap的无条件调用将使用我们的自定义swap运算符,从而跳过了std :: swap会导致的不必要的类构造和破坏。)

具体例子如下:

```cpp
namespace A {
    template<typename T>
    class smart_ptr {
    public:
        smart_ptr() noexcept : ptr_(new T()) {

        }

        smart_ptr(const T &ptr) noexcept : ptr_(new T(ptr)) {

        }

        smart_ptr(smart_ptr &rhs) noexcept {
            ptr_ = rhs.release();       // 释放所有权,此时rhs的ptr_指针为nullptr
        }

        void swap(smart_ptr &rhs) noexcept { // noexcept == throw() 保证不抛出异常
            using std::swap;
            swap(ptr_, rhs.ptr_);
        }

        T *release() noexcept {
            T *ptr = ptr_;
            ptr_ = nullptr;
            return ptr;
        }

        T *get() const noexcept {
            return ptr_;
        }

    private:
        T *ptr_;
    };

// 提供一个非成员swap函数for ADL(Argument Dependent Lookup)
    template<typename T>
    void swap(A::smart_ptr<T> &lhs, A::smart_ptr<T> &rhs) noexcept {
        lhs.swap(rhs);
    }
}
// 注释开启,会引发ADL冲突
//namespace std {
//    // 提供一个非成员swap函数for ADL(Argument Dependent Lookup)
//    template<typename T>
//    void swap(A::smart_ptr<T> &lhs, A::smart_ptr<T> &rhs) noexcept {
//        lhs.swap(rhs);
//    }
//
//}

int main() {

    using std::swap;
    A::smart_ptr<std::string> s1("hello"), s2("world");
    // 交换前
    std::cout << *s1.get() << " " << *s2.get() << std::endl;
    swap(s1, s2);      // 这里swap 能够通过Koenig搜索或者说ADL根据s1与s2的命名空间来查找swap函数
    // 交换后
    std::cout << *s1.get() << " " << *s2.get() << std::endl;
    s1=s2;
}
```

现在为了让上述的`s1=s2`完成工作,必须实现赋值运算符。

> 方法1

为了避免自赋值,通常采用下面写法 。

不好!  

不具备异常安全,只具备自我赋值安全性

```cpp
smart_ptr &operator=(const smart_ptr &rhs) {
    if (*this != rhs) {
        delete ptr_;
        ptr_ = new T(rhs.ptr_);  // 当new 发生异常,此时ptr_指向的而是一块被删除区域,而不是被赋值对象的区域
        return *this;
    }
    return *this;
}
```

> 方法2

如果new出现异常,ptr_会保持原装!  也可以处理自我赋值! 还是不够好!

**这样就会导致代码膨胀,于是导致了另一个问题:代码冗余**

```cpp
// 方法2:如果new出现异常,ptr_会保持原装!  也可以处理自我赋值! 还是不够好!
smart_ptr &operator=(const smart_ptr &rhs) {
    T *origin = ptr_;
    ptr_ = new T(rhs.ptr_);
    delete origin;
    return *this;
}
```

> 方法3

copy and swap 很好!

```cpp
smart_ptr &operator=(smart_ptr &rhs) noexcept {
    smart_ptr tmp(rhs);
    swap(tmp);
    return *this;
}
```

> 方法4

改为传值,同方法3!

```cpp
smart_ptr &operator=(smart_ptr rhs) noexcept {
    swap(rhs);
    return *this;
}
```

> C++11 move

我们在big three上加上move ctor与move assignment就构成了big five。

此时再次拓展上述的代码:

```cpp
// move ctor
smart_ptr(smart_ptr &&rhs) noexcept {
    std::cout << "move ctor" << std::endl;
    ptr_ = rhs.ptr_;
    if (ptr_)
        rhs.ptr_ = nullptr;
}

// move assignment
smart_ptr &operator=(smart_ptr &&rhs) noexcept {
    std::cout << "move assignment" << std::endl;
    smart_ptr tmp(rhs);
    swap(rhs);
    return *this;
}
```

**实际上,我们比那个不需要多写代码move assignment,copy-and-swap 技巧 和 move-and-swap 技巧是共享同一个函数的。**当copy构造为上述的方法4时,**对于C++ 11,编译器会依据参数是左值还是右值在拷贝构造函数和移动构造函数间进行选择:**

```cpp
smart_ptr &operator=(smart_ptr rhs) noexcept {
    swap(rhs);
    return *this;
}
```

所以当这个同上述写的

```cpp
smart_ptr &operator=(smart_ptr &&rhs) noexcept{}
```

同时存在,就会出现error: ambiguous overload for ‘operator=’ 。

调用处如下:

```cpp
A::smart_ptr<std::string> s1("hello"), s2("world");
A::smart_ptr<std::string> s3 = s1;
A::smart_ptr<std::string> s4 = std::move(s1);
```

- 如果是 s3 = s1,这样就会调用拷贝构造函数来初始化other(因为s1是左值),赋值操作符会与新创建的对象交换数据,深度拷贝。这就是copy and swap 惯用法的定义:构造一个副本,与副本交换数据,并让副本在作用域内自动销毁。
- 如果是s4 = std::move(s1),这样就会调用移动构造函数来初始化rhs(因为std::move(s1)是右值),所以这里没有深度拷贝,只有高效的数据转移。

因此也可以称呼它为“统一赋值操作符”,因为它合并了"拷贝赋值"与"移动赋值"。



================================================
FILE: codingStyleIdioms/4_copy-swap/copy-swapAndADL.cpp
================================================
//
// Created by light on 19-12-9.
//
#include <iostream>

// copy and swap : https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom
// ADL : https://stackoverflow.com/questions/8111677/what-is-argument-dependent-lookup-aka-adl-or-koenig-lookup

namespace A {
    template<typename T>
    class smart_ptr {
    public:
        smart_ptr() noexcept : ptr_(new T()) {

        }

        smar
Download .txt
gitextract_54wk3wyp/

├── .gitignore
├── README.md
├── README_EN.md
├── WORKSPACE
├── basic_content/
│   ├── abstract/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── abstract.cpp
│   │   ├── abstract_base.h
│   │   ├── derived_full.cpp
│   │   ├── interesting_facts1.cpp
│   │   ├── interesting_facts2.cpp
│   │   ├── interesting_facts3.cpp
│   │   ├── interesting_facts4.cpp
│   │   ├── interesting_facts5.cpp
│   │   └── pure_virtual.cpp
│   ├── assert/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── assert.c
│   │   └── ignore_assert.c
│   ├── bit/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── bit.cpp
│   ├── c_poly/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── c++_examp.cpp
│   │   └── c_examp.c
│   ├── const/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── class_const/
│   │   │   ├── c++11_example/
│   │   │   │   ├── BUILD
│   │   │   │   ├── apple.cpp
│   │   │   │   ├── apple.h
│   │   │   │   └── main.cpp
│   │   │   ├── first_example/
│   │   │   │   ├── BUILD
│   │   │   │   ├── apple.cpp
│   │   │   │   ├── apple.h
│   │   │   │   └── main.cpp
│   │   │   ├── overload_example/
│   │   │   │   ├── BUILD
│   │   │   │   ├── apple.cpp
│   │   │   │   ├── apple.h
│   │   │   │   └── main.cpp
│   │   │   └── static_example/
│   │   │       ├── BUILD
│   │   │       ├── apple.cpp
│   │   │       ├── apple.h
│   │   │       └── main.cpp
│   │   ├── const_function.cpp
│   │   ├── const_num.cpp
│   │   ├── extern_const/
│   │   │   ├── BUILD
│   │   │   ├── const_file1.cpp
│   │   │   ├── const_file2.cpp
│   │   │   ├── file1.cpp
│   │   │   └── file2.cpp
│   │   └── funciton_const/
│   │       ├── condition1/
│   │       │   ├── BUILD
│   │       │   ├── condition1.cpp
│   │       │   ├── condition2.cpp
│   │       │   └── condition3.cpp
│   │       ├── condition2/
│   │       │   ├── BUILD
│   │       │   ├── condition1.cpp
│   │       │   ├── condition2.cpp
│   │       │   └── condition3.cpp
│   │       └── condition3/
│   │           ├── BUILD
│   │           └── condition1.cpp
│   ├── decltype/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── decltype.cpp
│   ├── enum/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── classic_practice.cpp
│   │   └── tradition_color.cpp
│   ├── explicit/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── explicit.cpp
│   ├── extern/
│   │   ├── README.md
│   │   ├── extern_c/
│   │   │   ├── BUILD
│   │   │   ├── add.c
│   │   │   ├── add.cpp
│   │   │   └── add.h
│   │   └── extern_c++/
│   │       ├── BUILD
│   │       ├── add.c
│   │       ├── add.cpp
│   │       └── add.h
│   ├── friend/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── friend_class.cpp
│   │   └── friend_func.cpp
│   ├── func_pointer/
│   │   ├── BUILD
│   │   └── func_pointer.cpp
│   ├── inline/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── inline.cpp
│   │   ├── inline.h
│   │   └── inline_virtual.cpp
│   ├── macro/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── do_while.cpp
│   │   └── sig_examp.cpp
│   ├── maohao/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── maohao.cpp
│   ├── pointer_refer/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── copy_construct.cpp
│   │   └── effec.cpp
│   ├── sizeof/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── blackclass.cpp
│   │   ├── genA.cpp
│   │   ├── geninhe.cpp
│   │   ├── moreinhe.cpp
│   │   ├── morevir.cpp
│   │   ├── static.cpp
│   │   ├── virinhe.cpp
│   │   └── virmoreinhe.cpp
│   ├── static/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── nostatic_class.cpp
│   │   ├── static_class.cpp
│   │   ├── static_demo.cpp
│   │   ├── static_error_variable.cpp
│   │   ├── static_funciton.cpp
│   │   └── static_variable.cpp
│   ├── struct/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── ext_struct_func.cpp
│   │   ├── struct_func.c
│   │   ├── struct_func.cpp
│   │   ├── struct_func_func.cpp
│   │   └── stu
│   ├── struct_class/
│   │   └── README.md
│   ├── this/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── person.cpp
│   ├── union/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── union.cpp
│   ├── using/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── derived_base.cpp
│   │   ├── using_derived.cpp
│   │   ├── using_global.cpp
│   │   └── using_typedef.cpp
│   ├── virtual/
│   │   ├── README.md
│   │   ├── set1/
│   │   │   ├── BUILD
│   │   │   └── emp.cpp
│   │   ├── set2/
│   │   │   ├── BUILD
│   │   │   └── default_arg.cpp
│   │   ├── set3/
│   │   │   ├── BUILD
│   │   │   ├── copy_consrtuct.cpp
│   │   │   ├── full_virde.cpp
│   │   │   ├── inline_virtual.cpp
│   │   │   ├── static_error.cpp
│   │   │   ├── vir_con.cpp
│   │   │   ├── vir_de.cpp
│   │   │   ├── virtual_function.cpp
│   │   │   ├── virtual_function1.cpp
│   │   │   └── virtual_inline.cpp
│   │   └── set4/
│   │       ├── BUILD
│   │       ├── rtti.cpp
│   │       └── warn_rtti.cpp
│   ├── volatile/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── noopt_vola.cpp
│   │   └── volatile.cpp
│   └── vptr_vtable/
│       ├── BUILD
│       ├── README.md
│       └── vptr1.cpp
├── codingStyleIdioms/
│   ├── 1_classInitializers/
│   │   ├── 1.1_nest.cpp
│   │   ├── 1.2_nodefault_ctor.cpp
│   │   ├── 1.3_const.cpp
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── initializer.cpp
│   ├── 2_enumclass/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── namespace.cpp
│   ├── 3_RAII/
│   │   ├── BUILD
│   │   ├── RAII.cpp
│   │   ├── RAII.md
│   │   ├── RAII_fstram.cpp
│   │   ├── c++_example.cpp
│   │   ├── c++_example1.cpp
│   │   ├── c++_example2.cpp
│   │   └── c_example.cpp
│   ├── 4_copy-swap/
│   │   ├── BUILD
│   │   ├── README.md
│   │   └── copy-swapAndADL.cpp
│   ├── 5_pImpl/
│   │   ├── BUILD
│   │   ├── README.md
│   │   ├── noPimpl.cpp
│   │   ├── pimpl.cpp
│   │   ├── pimplTime.cpp
│   │   └── pimplTime.h
│   └── README.md
├── concurrency/
│   ├── Threading_In_CPlusPlus/
│   │   ├── 1.thread/
│   │   │   ├── BUILD
│   │   │   ├── intro.cpp
│   │   │   └── thread.cpp
│   │   ├── 2.create_type/
│   │   │   ├── 1.function_pointer.cpp
│   │   │   ├── 2.lambda_function.cpp
│   │   │   ├── 3.functor.cpp
│   │   │   ├── 4.no_static_member_function.cpp
│   │   │   ├── 5.static_member_function.cpp
│   │   │   └── BUILD
│   │   ├── 3.join_detach/
│   │   │   ├── BUILD
│   │   │   ├── detach.cpp
│   │   │   └── join.cpp
│   │   └── 4.mutex/
│   │       ├── BUILD
│   │       ├── an_example_of_bank_account.cpp
│   │       └── critical_section.cpp
│   └── concurrency_v1/
│       ├── chapter1/
│       │   ├── 1_helloworld.cpp
│       │   └── BUILD
│       └── chapter2/
│           ├── 2.1_basic.cpp
│           ├── 2.2_transfer.cpp
│           ├── 2.3_ownership.cpp
│           ├── 2.4_runtime.cpp
│           ├── 2_5_id.cpp
│           └── BUILD
├── cpp2.0/
│   └── cpp11/
│       ├── BUILD
│       ├── README.md
│       ├── alias.cpp
│       ├── auto.cpp
│       ├── constexpr.cpp
│       ├── decltype.cpp
│       ├── default_delete.cpp
│       ├── explicit.cpp
│       ├── final.cpp
│       ├── hash.cpp
│       ├── initializer.cpp
│       ├── lambda.cpp
│       ├── move.cpp
│       ├── noexcept.cpp
│       ├── nullptr.cpp
│       ├── override.cpp
│       ├── rvalue.cpp
│       ├── template_template.cpp
│       ├── tuple.cpp
│       ├── type_alias.cpp
│       ├── uniform_initialization.cpp
│       └── variadic/
│           ├── BUILD
│           ├── variadic.cpp
│           ├── variadic1.cpp
│           ├── variadic2.cpp
│           ├── variadic3_4.cpp
│           ├── variadic5.cpp
│           ├── variadic6.cpp
│           └── variadic7.cpp
├── design_pattern/
│   ├── producer_consumer/
│   │   ├── BUILD
│   │   └── producer_consumer.cpp
│   └── singleton/
│       ├── README.md
│       ├── barrier_singleton.cpp
│       ├── cpulpuls11_singleton.cpp
│       ├── dcl_singleton.cpp
│       ├── hungrysingleton.cpp
│       ├── iazysingleton.cpp
│       ├── lock_singleton.cpp
│       ├── pthreadoncesingleton.cpp
│       └── static_local_singleton.cpp
├── effective_cpp/
│   ├── 2.cpp
│   └── BUILD
├── english/
│   └── basic_content/
│       ├── abstract/
│       │   ├── README.md
│       │   ├── abstract.cpp
│       │   ├── derived_full.cpp
│       │   ├── interesting_facts1.cpp
│       │   ├── interesting_facts2.cpp
│       │   ├── interesting_facts3.cpp
│       │   ├── interesting_facts4.cpp
│       │   ├── interesting_facts5.cpp
│       │   ├── pure_virtual.cpp
│       │   └── test.cpp
│       ├── assert/
│       │   ├── README.md
│       │   ├── assert.c
│       │   └── ignore_assert.c
│       ├── bit/
│       │   ├── README.md
│       │   └── learn.cpp
│       ├── c_poly/
│       │   ├── README.md
│       │   ├── c++_examp
│       │   ├── c++_examp.cpp
│       │   ├── c_examp
│       │   └── c_examp.c
│       ├── const/
│       │   ├── README.md
│       │   ├── class_const/
│       │   │   ├── c++11_example/
│       │   │   │   ├── apple.cpp
│       │   │   │   ├── main
│       │   │   │   └── main.cpp
│       │   │   ├── first_example/
│       │   │   │   ├── apple.cpp
│       │   │   │   └── main.cpp
│       │   │   ├── overload_example/
│       │   │   │   ├── apple.cpp
│       │   │   │   ├── main
│       │   │   │   └── main.cpp
│       │   │   └── static_example/
│       │   │       ├── apple.cpp
│       │   │       ├── main
│       │   │       └── main.cpp
│       │   ├── const_function.cpp
│       │   ├── const_num.cpp
│       │   ├── extern_const/
│       │   │   ├── const_file1.cpp
│       │   │   ├── const_file2.cpp
│       │   │   ├── file1.cpp
│       │   │   └── file2.cpp
│       │   └── funciton_const/
│       │       ├── condition1/
│       │       │   ├── condition1.cpp
│       │       │   ├── condition2.cpp
│       │       │   └── condition3.cpp
│       │       ├── condition2/
│       │       │   ├── condition1
│       │       │   ├── condition1.cpp
│       │       │   ├── condition2.cpp
│       │       │   ├── condition3
│       │       │   └── condition3.cpp
│       │       └── condition3/
│       │           ├── condition1
│       │           └── condition1.cpp
│       ├── decltype/
│       │   ├── README.md
│       │   ├── decltype
│       │   └── decltype.cpp
│       ├── enum/
│       │   ├── README.md
│       │   ├── classic_practice
│       │   ├── classic_practice.cpp
│       │   └── tradition_color.cpp
│       ├── explicit/
│       │   ├── README.md
│       │   └── explicit.cpp
│       ├── extern/
│       │   ├── README.md
│       │   ├── extern_c/
│       │   │   ├── add.c
│       │   │   ├── add.cpp
│       │   │   ├── add.h
│       │   │   ├── add.o
│       │   │   └── main
│       │   └── extern_c++/
│       │       ├── add.c
│       │       ├── add.cpp
│       │       ├── add.h
│       │       ├── add.o
│       │       └── main
│       ├── friend/
│       │   ├── README.md
│       │   ├── friend_class
│       │   ├── friend_class.cpp
│       │   ├── friend_func
│       │   └── friend_func.cpp
│       ├── func_pointer/
│       │   ├── func1
│       │   └── func_pointer.cpp
│       ├── inline/
│       │   ├── README.md
│       │   ├── inline
│       │   ├── inline.cpp
│       │   ├── inline.h
│       │   ├── inline_virtual.cpp
│       │   └── iv
│       ├── macro/
│       │   ├── README.md
│       │   ├── do_while
│       │   ├── do_while.cpp
│       │   ├── sig_examp
│       │   └── sig_examp.cpp
│       ├── maohao/
│       │   ├── .README.md.un~
│       │   ├── README.md
│       │   ├── README.md~
│       │   └── maohao.cpp
│       ├── pointer_refer/
│       │   ├── README.md
│       │   ├── copy_construct
│       │   ├── copy_construct.cpp
│       │   ├── effec
│       │   └── effec.cpp
│       ├── sizeof/
│       │   ├── README.md
│       │   ├── blackclass.cpp
│       │   ├── genA.cpp
│       │   ├── geninhe.cpp
│       │   ├── moreinhe.cpp
│       │   ├── morevir.cpp
│       │   ├── static.cpp
│       │   ├── virinhe.cpp
│       │   └── virmoreinhe.cpp
│       ├── static/
│       │   ├── README.md
│       │   ├── demo
│       │   ├── nostatic_class.cpp
│       │   ├── static_class.cpp
│       │   ├── static_demo.cpp
│       │   ├── static_error_variable.cpp
│       │   ├── static_funciton.cpp
│       │   └── static_variable.cpp
│       ├── struct/
│       │   ├── README.md
│       │   ├── ext
│       │   ├── ext_struct_func.cpp
│       │   ├── sf
│       │   ├── stff
│       │   ├── struct_func
│       │   ├── struct_func.c
│       │   ├── struct_func.cpp
│       │   ├── struct_func_func.cpp
│       │   └── stu
│       ├── struct_class/
│       │   └── README.md
│       ├── this/
│       │   ├── README.md
│       │   ├── person
│       │   └── person.cpp
│       ├── union/
│       │   ├── README.md
│       │   ├── union
│       │   └── union.cpp
│       ├── using/
│       │   ├── README.md
│       │   ├── derived_base
│       │   ├── derived_base.cpp
│       │   ├── using_derived
│       │   ├── using_derived.cpp
│       │   ├── using_global
│       │   ├── using_global.cpp
│       │   ├── using_typedef
│       │   └── using_typedef.cpp
│       ├── virtual/
│       │   ├── README.md
│       │   ├── set1/
│       │   │   ├── emp
│       │   │   └── emp.cpp
│       │   ├── set2/
│       │   │   └── default_arg.cpp
│       │   ├── set3/
│       │   │   ├── copy_consrtuct.cpp
│       │   │   ├── full_virde.cpp
│       │   │   ├── inline_virtual.cpp
│       │   │   ├── static_error.cpp
│       │   │   ├── vir_con.cpp
│       │   │   ├── vir_de.cpp
│       │   │   ├── virtual_function.cpp
│       │   │   ├── virtual_function1.cpp
│       │   │   └── virtual_inline.cpp
│       │   └── set4/
│       │       ├── rtti
│       │       ├── rtti.cpp
│       │       └── warn_rtti.cpp
│       ├── volatile/
│       │   ├── README.md
│       │   ├── noopt_vola.cpp
│       │   ├── nv
│       │   └── volatile.cpp
│       └── vptr_vtable/
│           ├── README.md
│           └── vptr1.cpp
├── extension/
│   └── some_problem/
│       └── string_int.md
├── learn_class/
│   └── modern_cpp_30/
│       ├── RAII/
│       │   ├── BUILD
│       │   ├── RAII.cpp
│       │   ├── heap.cpp
│       │   └── stack.cpp
│       ├── SFINAE/
│       │   ├── README.md
│       │   ├── SFINAE.cpp
│       │   └── sfinae paper/
│       │       ├── auto.cpp
│       │       ├── blending1.cpp
│       │       ├── blending2.cpp
│       │       ├── combiningAndGenius.cpp
│       │       ├── constexpr.cpp
│       │       ├── decltype.cpp
│       │       ├── fis_valid.cpp
│       │       ├── hana.cpp
│       │       ├── is_valid.cpp
│       │       ├── lambda.cpp
│       │       ├── overload1.cpp
│       │       ├── overload2.cpp
│       │       ├── p1SFINAE.cpp
│       │       ├── p2SFINAE.cpp
│       │       ├── packis_valid.cpp
│       │       ├── serialize.cpp
│       │       ├── sizeof1.cpp
│       │       ├── sizeof2.cpp
│       │       ├── structData.h
│       │       └── timeGenius.cpp
│       ├── compilercompute/
│       │   ├── BUILD
│       │   ├── IF.cpp
│       │   ├── WhileLoop.cpp
│       │   ├── factorial.cpp
│       │   └── fmap.cpp
│       ├── compilerpoly/
│       │   ├── BUILD
│       │   ├── README.md
│       │   └── template.cpp
│       ├── constexpr/
│       │   ├── BUILD
│       │   ├── container.cpp
│       │   ├── newconstexpr.cpp
│       │   ├── output_container.h
│       │   ├── sqrt.cpp
│       │   └── test3.cpp
│       ├── container1/
│       │   ├── BUILD
│       │   ├── container.cpp
│       │   ├── output_container.h
│       │   └── vector_l.cpp
│       ├── container2/
│       │   ├── BUILD
│       │   ├── array.cpp
│       │   ├── hash.cpp
│       │   ├── priority_queue.cpp
│       │   ├── relacontainer.cpp
│       │   └── unorder.cpp
│       ├── exception/
│       │   ├── BUILD
│       │   └── exception.cpp
│       ├── functionLambda/
│       │   ├── BUILD
│       │   ├── adder.cpp
│       │   ├── autoLambda.cpp
│       │   └── function.cpp
│       ├── literalAssert/
│       │   ├── BUILD
│       │   ├── assert.cpp
│       │   ├── default_delete.cpp
│       │   ├── literal.cpp
│       │   └── overridefinal.cpp
│       ├── memorymodel_atomic/
│       │   ├── barrier_singleton.cpp
│       │   ├── cpulpuls11_singleton.cpp
│       │   ├── dcl_singleton.cpp
│       │   ├── hungrysingleton.cpp
│       │   ├── iazysingleton.cpp
│       │   ├── lock_singleton.cpp
│       │   ├── pthreadoncesingleton.cpp
│       │   └── static_local_singleton.cpp
│       ├── obj/
│       │   ├── BUILD
│       │   ├── all.cpp
│       │   ├── obj1.cpp
│       │   ├── obj2.cpp
│       │   ├── obj3.cpp
│       │   ├── obj4.cpp
│       │   └── obj5.cpp
│       ├── reference/
│       │   ├── BUILD
│       │   ├── collapses.cpp
│       │   ├── forward.cpp
│       │   ├── lifetime.cpp
│       │   ├── ref.cpp
│       │   ├── reference.cpp
│       │   └── shape.h
│       └── smart_ptr/
│           ├── README.md
│           ├── auto_scope.cpp
│           ├── shared_ptr.cpp
│           ├── unique_ptr.cpp
│           └── unique_ptr_U.cpp
├── practical_exercises/
│   ├── 10_day_practice/
│   │   ├── day1/
│   │   │   ├── BUILD
│   │   │   ├── annotate.cpp
│   │   │   ├── print.cpp
│   │   │   ├── runnian.cpp
│   │   │   └── union.cpp
│   │   ├── day10/
│   │   │   ├── file/
│   │   │   │   ├── 10-4.cpp
│   │   │   │   ├── 12-1.cpp
│   │   │   │   ├── 12-2.cpp
│   │   │   │   ├── 12-3.cpp
│   │   │   │   ├── 12-5.cpp
│   │   │   │   ├── 12-6.cpp
│   │   │   │   ├── 12-7.cpp
│   │   │   │   ├── 12-9.cpp
│   │   │   │   ├── BUILD
│   │   │   │   ├── input/
│   │   │   │   │   ├── BUILD
│   │   │   │   │   ├── get.cpp
│   │   │   │   │   ├── get2.cpp
│   │   │   │   │   └── getline.cpp
│   │   │   │   └── practice.cpp
│   │   │   └── readme.md
│   │   ├── day2/
│   │   │   ├── BUILD
│   │   │   ├── compute.cpp
│   │   │   ├── enum.cpp
│   │   │   ├── hanoi.cpp
│   │   │   ├── pow.cpp
│   │   │   ├── rec1.cpp
│   │   │   ├── rec2.cpp
│   │   │   ├── shaizi.cpp
│   │   │   ├── st.cpp
│   │   │   └── static.cpp
│   │   ├── day3/
│   │   │   ├── BUILD
│   │   │   ├── inline.cpp
│   │   │   ├── pratice.cpp
│   │   │   ├── predeclare.cpp
│   │   │   ├── static_data.cpp
│   │   │   ├── static_member1.cpp
│   │   │   ├── static_member2.cpp
│   │   │   └── swap.cpp
│   │   ├── day4/
│   │   │   ├── clock/
│   │   │   │   ├── BUILD
│   │   │   │   ├── operator.cpp
│   │   │   │   └── operator_plus.cpp
│   │   │   ├── const/
│   │   │   │   ├── BUILD
│   │   │   │   ├── obj_func.cpp
│   │   │   │   ├── obj_ref.cpp
│   │   │   │   └── readme.md
│   │   │   ├── copy_ctor/
│   │   │   │   ├── BUILD
│   │   │   │   ├── clock.cpp
│   │   │   │   └── clock.h
│   │   │   └── friend/
│   │   │       ├── BUILD
│   │   │       ├── class.cpp
│   │   │       ├── func.cpp
│   │   │       └── readme.md
│   │   ├── day5/
│   │   │   ├── ctor_dtor/
│   │   │   │   ├── BUILD
│   │   │   │   ├── cseq.cpp
│   │   │   │   ├── ctor.cpp
│   │   │   │   ├── ctor_d.cpp
│   │   │   │   ├── noctor.cpp
│   │   │   │   ├── param.cpp
│   │   │   │   ├── readme.md
│   │   │   │   └── seq.cpp
│   │   │   ├── inherit_access/
│   │   │   │   ├── BUILD
│   │   │   │   ├── private.cpp
│   │   │   │   ├── protected.cpp
│   │   │   │   ├── protected_inherit.cpp
│   │   │   │   ├── public.cpp
│   │   │   │   └── readme.md
│   │   │   ├── rela/
│   │   │   │   ├── BUILD
│   │   │   │   ├── readme.md
│   │   │   │   └── rela.cpp
│   │   │   ├── rule/
│   │   │   │   ├── BUILD
│   │   │   │   ├── direct.cpp
│   │   │   │   └── readme.md
│   │   │   └── virtual/
│   │   │       ├── BUILD
│   │   │       ├── example1.cpp
│   │   │       ├── example2.cpp
│   │   │       ├── init.cpp
│   │   │       ├── readme.md
│   │   │       └── seq.cpp
│   │   ├── day6/
│   │   │   ├── abstract_class/
│   │   │   │   ├── BUILD
│   │   │   │   └── main.cpp
│   │   │   ├── readme.md
│   │   │   └── virtual_func/
│   │   │       ├── BUILD
│   │   │       ├── example.cpp
│   │   │       ├── virtual.cpp
│   │   │       ├── virtual_dtor.cpp
│   │   │       ├── virtual_feature.cpp
│   │   │       └── vis.cpp
│   │   ├── day7/
│   │   │   ├── binary_operator/
│   │   │   │   ├── BUILD
│   │   │   │   ├── friend_operator.cpp
│   │   │   │   └── operator.cpp
│   │   │   ├── brackets/
│   │   │   │   ├── BUILD
│   │   │   │   └── brac.cpp
│   │   │   ├── equal_operator/
│   │   │   │   ├── BUILD
│   │   │   │   └── equal_operator.cpp
│   │   │   ├── example/
│   │   │   │   ├── BUILD
│   │   │   │   └── example.cpp
│   │   │   ├── index_parentheses/
│   │   │   │   ├── BUILD
│   │   │   │   └── example.cpp
│   │   │   ├── readme.md
│   │   │   ├── subscript_operator/
│   │   │   │   ├── BUILD
│   │   │   │   └── subscript_operator.cpp
│   │   │   └── unary_operator/
│   │   │       ├── BUILD
│   │   │       ├── time_counter.cpp
│   │   │       └── time_increase.cpp
│   │   ├── day8/
│   │   │   ├── class_template/
│   │   │   │   ├── BUILD
│   │   │   │   ├── spec.cpp
│   │   │   │   └── stack.cpp
│   │   │   ├── func/
│   │   │   │   ├── BUILD
│   │   │   │   ├── main.cpp
│   │   │   │   ├── max.cpp
│   │   │   │   ├── max_spec.cpp
│   │   │   │   └── sort.cpp
│   │   │   ├── readme.md
│   │   │   └── stl/
│   │   │       ├── BUILD
│   │   │       └── map.cpp
│   │   ├── day9/
│   │   │   ├── exception/
│   │   │   │   ├── 1.cpp
│   │   │   │   ├── 10.cpp
│   │   │   │   ├── 2.cpp
│   │   │   │   ├── 3.cpp
│   │   │   │   ├── 4.cpp
│   │   │   │   ├── 5.cpp
│   │   │   │   ├── 6.cpp
│   │   │   │   ├── 7-1.cpp
│   │   │   │   ├── 7.cpp
│   │   │   │   ├── 8.cpp
│   │   │   │   ├── 9-2.cpp
│   │   │   │   ├── 9.cpp
│   │   │   │   └── BUILD
│   │   │   └── readme.md
│   │   └── readme.md
│   └── key_exercises/
│       ├── BUILD
│       ├── README.md
│       ├── array.cpp
│       ├── array_template.cpp
│       ├── bracket_overloading.cpp
│       ├── clock.cpp
│       ├── func_temp.cpp
│       ├── io_operator.cpp
│       ├── io_operator_overload.cpp
│       ├── map_insert_look.cpp
│       ├── operator_cast.cpp
│       ├── operator_circle.cpp
│       ├── output.cpp
│       ├── override.cpp
│       ├── read_file.cpp
│       ├── stack.cpp
│       └── try.cpp
├── proj/
│   └── README.md
├── src_analysis/
│   └── stl/
│       ├── array.md
│       ├── deque.md
│       ├── hashtable.md
│       ├── iterator.md
│       ├── list.md
│       ├── map_multimap.md
│       ├── myhashtable.md
│       ├── queue_stack.md
│       ├── rb_tree.md
│       ├── set_multiset.md
│       ├── traits.md
│       ├── typename.md
│       ├── unordered_map.md
│       ├── vector.md
│       └── 谈谈STL设计之EBO优化.md
└── tool/
    ├── C++的Debug工具dbg-macro.md
    ├── output/
    │   ├── BUILD
    │   ├── container.cpp
    │   └── output_container.h
    ├── 像Python一样玩CC++.md
    └── 用rr来进行debug.md
Download .txt
SYMBOL INDEX (1846 symbols across 432 files)

FILE: basic_content/abstract/abstract.cpp
  class A (line 14) | class A {
    method g (line 17) | void g() { this->f(); }
    method A (line 18) | A() {}
  class B (line 20) | class B : public A {
    method f (line 22) | void f() { cout << "B:f()" << endl; }
  function main (line 24) | int main() {

FILE: basic_content/abstract/abstract_base.h
  function class (line 14) | class AbstractBase {

FILE: basic_content/abstract/derived_full.cpp
  class Base (line 12) | class Base {
    method getX (line 17) | int getX() { return x; }
  class Derived (line 20) | class Derived : public Base {
    method fun (line 22) | void fun() { cout << "fun() called"; }
  function main (line 25) | int main(void) {

FILE: basic_content/abstract/interesting_facts1.cpp
  class Test (line 15) | class Test {
    method getX (line 20) | int getX() { return x; }
  function main (line 23) | int main(void) {

FILE: basic_content/abstract/interesting_facts2.cpp
  class Base (line 15) | class Base {
    method getX (line 20) | int getX() { return x; }
  class Derived (line 22) | class Derived : public Base {
    method show (line 24) | void show() { cout << "In Derived \n"; }
    method Derived (line 25) | Derived() {}
  function main (line 27) | int main(void) {

FILE: basic_content/abstract/interesting_facts3.cpp
  class Base (line 12) | class Base {
    method getX (line 17) | int getX() { return x; }
  class Derived (line 19) | class Derived : public Base {
  function main (line 23) | int main(void) {

FILE: basic_content/abstract/interesting_facts4.cpp
  class Base (line 13) | class Base {
    method Base (line 19) | Base(int i) { x = i; }
  class Derived (line 22) | class Derived : public Base {
    method Derived (line 26) | Derived(int i, int j) : Base(i) { y = j; }
    method fun (line 27) | void fun() { cout << "x = " << x << ", y = " << y; }
  function main (line 30) | int main(void) {

FILE: basic_content/abstract/interesting_facts5.cpp
  class Base (line 13) | class Base {
    method Base (line 15) | Base() { cout << "Constructor: Base" << endl; }
  class Derived (line 19) | class Derived : public Base {
    method Derived (line 21) | Derived() { cout << "Constructor: Derived" << endl; }
  function main (line 25) | int main() {

FILE: basic_content/abstract/pure_virtual.cpp
  class A (line 14) | class A {
  function main (line 22) | int main() {

FILE: basic_content/assert/assert.c
  function main (line 4) | int main()

FILE: basic_content/assert/ignore_assert.c
  function main (line 13) | int main(){

FILE: basic_content/bit/bit.cpp
  type stuff (line 4) | struct stuff {
  function main (line 11) | int main() {

FILE: basic_content/c_poly/c++_examp.cpp
  class A (line 12) | class A {
    method f (line 14) | virtual void f() //虚函数实现
  class B (line 20) | class B : public A // 必须为共有继承,否则后面调用不到,class默认为私有继承!
    method f (line 23) | virtual void f() //虚函数实现,子类中virtual关键字可以没有
  function main (line 29) | int main() {

FILE: basic_content/c_poly/c_examp.c
  type A (line 17) | typedef struct _A
  type B (line 26) | typedef struct _B
  function FunA (line 31) | void FunA()
  function FunB (line 36) | void FunB()
  function main (line 42) | int main()

FILE: basic_content/const/class_const/c++11_example/apple.h
  function class (line 3) | class Apple {

FILE: basic_content/const/class_const/c++11_example/main.cpp
  function main (line 4) | int main() {

FILE: basic_content/const/class_const/first_example/apple.h
  function class (line 3) | class Apple {

FILE: basic_content/const/class_const/first_example/main.cpp
  function main (line 5) | int main() {

FILE: basic_content/const/class_const/overload_example/apple.h
  function class (line 3) | class Apple {

FILE: basic_content/const/class_const/overload_example/main.cpp
  function main (line 5) | int main() {

FILE: basic_content/const/class_const/static_example/apple.h
  function class (line 2) | class Apple {

FILE: basic_content/const/class_const/static_example/main.cpp
  function main (line 3) | int main() {

FILE: basic_content/const/const_function.cpp
  function f (line 4) | void f(const int i) {
  function main (line 9) | int main() { f(1); }

FILE: basic_content/const/const_num.cpp
  function main (line 3) | int main() {

FILE: basic_content/const/extern_const/const_file2.cpp
  function main (line 8) | int main() { std::cout << ext << std::endl; }

FILE: basic_content/const/extern_const/file2.cpp
  function main (line 8) | int main() { std::cout << (ext + 10) << std::endl; }

FILE: basic_content/const/funciton_const/condition1/condition1.cpp
  function main (line 4) | int main() {

FILE: basic_content/const/funciton_const/condition1/condition2.cpp
  function main (line 4) | int main() {

FILE: basic_content/const/funciton_const/condition1/condition3.cpp
  function main (line 4) | int main() {

FILE: basic_content/const/funciton_const/condition2/condition1.cpp
  function main (line 3) | int main() {

FILE: basic_content/const/funciton_const/condition2/condition2.cpp
  function main (line 3) | int main() {

FILE: basic_content/const/funciton_const/condition2/condition3.cpp
  function main (line 3) | int main() {

FILE: basic_content/const/funciton_const/condition3/condition1.cpp
  function main (line 4) | int main() {

FILE: basic_content/decltype/decltype.cpp
  function multiply (line 9) | auto multiply(T x, T y) -> decltype(x * y) {
  function main (line 13) | int main() {

FILE: basic_content/enum/classic_practice.cpp
  type Color (line 6) | namespace Color {
    type Type (line 7) | enum Type { RED = 15, YELLOW, BLUE }
  type Color1 (line 21) | struct Color1 {
    type Type (line 22) | enum Type { RED = 102, YELLOW, BLUE }
  type Color2 (line 29) | enum class Color2 { RED = 2, YELLOW, BLUE }
  type Color3 (line 31) | enum class Color3 : char
  type Color3 (line 34) | enum class Color3 : char { RED = 'r', BLUE }
  function main (line 36) | int main() {

FILE: basic_content/enum/tradition_color.cpp
  type Color (line 4) | enum Color { RED, BLUE }
  type Feeling (line 5) | enum Feeling { EXCITED, BLUE }
  function main (line 7) | int main() {

FILE: basic_content/explicit/explicit.cpp
  type A (line 5) | struct A {
    method A (line 6) | A(int) {}
  type B (line 10) | struct B {
    method B (line 11) | explicit B(int) {}
  function doA (line 15) | void doA(A a) {}
  function doB (line 17) | void doB(B b) {}
  function main (line 19) | int main() {

FILE: basic_content/extern/extern_c++/add.c
  function add (line 3) | int add(int x,int y) {

FILE: basic_content/extern/extern_c++/add.cpp
  function main (line 6) | int main() {

FILE: basic_content/extern/extern_c/add.c
  function main (line 2) | int main() {

FILE: basic_content/extern/extern_c/add.cpp
  function add (line 3) | int add(int x, int y) { return x + y; }

FILE: basic_content/friend/friend_class.cpp
  class A (line 5) | class A {
    method A (line 7) | A(int _a) : a(_a){}
  class B (line 14) | class B {
    method getb (line 16) | int getb(A ca) { return ca.a; }
  function main (line 19) | int main() {

FILE: basic_content/friend/friend_func.cpp
  class A (line 5) | class A {
    method A (line 7) | A(int _a) : a(_a){}
  function geta (line 13) | int geta(A &ca) { return ca.a; }
  function main (line 15) | int main() {

FILE: basic_content/func_pointer/func_pointer.cpp
  function myfunc (line 23) | void myfunc(void) { cout << "asda" << endl; }
  function glFun (line 25) | void glFun(int a) { cout << a << endl; }
  function main (line 26) | int main() {

FILE: basic_content/inline/inline.cpp
  function Foo (line 16) | inline int Foo(int x, int y) // 函数定义
  function main (line 34) | int main() { cout << Foo(1, 2) << endl; }

FILE: basic_content/inline/inline.h
  function class (line 2) | class A {

FILE: basic_content/inline/inline_virtual.cpp
  class Base (line 3) | class Base {
    method who (line 5) | inline virtual void who() { cout << "I am Base\n"; }
  class Derived (line 8) | class Derived : public Base {
    method who (line 10) | inline void who() // 不写inline时隐式内联
  function main (line 16) | int main() {

FILE: basic_content/macro/do_while.cpp
  function f (line 19) | int f() {
  function ff (line 36) | int ff() {
  function fc (line 56) | int fc() {
  function main (line 67) | int main() {

FILE: basic_content/macro/sig_examp.cpp
  function main (line 36) | int main() {

FILE: basic_content/maohao/maohao.cpp
  class A (line 6) | class A {
  function main (line 12) | int main() {

FILE: basic_content/pointer_refer/copy_construct.cpp
  class Copyable (line 13) | class Copyable {
    method Copyable (line 15) | Copyable() {}
    method Copyable (line 16) | Copyable(const Copyable &o) { cout << "Copied" << endl; }
  function Copyable (line 18) | Copyable ReturnRvalue() {
    method Copyable (line 15) | Copyable() {}
    method Copyable (line 16) | Copyable(const Copyable &o) { cout << "Copied" << endl; }
  function AcceptVal (line 21) | void AcceptVal(Copyable a) {}
  function AcceptRef (line 22) | void AcceptRef(const Copyable &a) {}
  function main (line 24) | int main() {

FILE: basic_content/pointer_refer/effec.cpp
  function test1 (line 3) | void test1(int *p) {
  function test2 (line 8) | void test2(int &p) {
  function main (line 13) | int main() {

FILE: basic_content/sizeof/blackclass.cpp
  class A (line 12) | class A {}
  function main (line 13) | int main() {

FILE: basic_content/sizeof/genA.cpp
  class A (line 14) | class A {
  function main (line 24) | int main() {

FILE: basic_content/sizeof/geninhe.cpp
  class A (line 15) | class A {
  class B (line 36) | class B : A {
  class C (line 44) | class C {
  class A1 (line 49) | class A1 {
    method fun (line 50) | virtual void fun() {}
  class C1 (line 52) | class C1 : public A1 {}
  function main (line 54) | int main() {

FILE: basic_content/sizeof/moreinhe.cpp
  class A (line 13) | class A {
  class B (line 19) | class B {
  class C (line 28) | class C : A, B {
  function main (line 32) | int main() {

FILE: basic_content/sizeof/morevir.cpp
  class A (line 13) | class A {
  function main (line 20) | int main() {

FILE: basic_content/sizeof/static.cpp
  class A (line 13) | class A {
  function main (line 22) | int main() {

FILE: basic_content/sizeof/virinhe.cpp
  class A (line 13) | class A {
    method fun (line 14) | virtual void fun() {}
  class B (line 17) | class B {
    method fun2 (line 18) | virtual void fun2() {}
  class C (line 20) | class C : virtual public A, virtual public B {
    method fun3 (line 22) | virtual void fun3() {}
  function main (line 25) | int main() {

FILE: basic_content/sizeof/virmoreinhe.cpp
  class A (line 13) | class A {
    method fun (line 14) | virtual void fun() {}
  class B (line 17) | class B {
    method fun2 (line 18) | virtual void fun2() {}
  class C (line 20) | class C : public A, public B {
    method fun3 (line 22) | virtual void fun3() {}
  function main (line 25) | int main() {

FILE: basic_content/static/nostatic_class.cpp
  class Apple (line 4) | class Apple {
    method Apple (line 8) | Apple() {
  function main (line 15) | int main() {

FILE: basic_content/static/static_class.cpp
  class Apple (line 4) | class Apple {
    method Apple (line 8) | Apple() {
  function main (line 15) | int main() {

FILE: basic_content/static/static_demo.cpp
  function demo (line 7) | void demo() {
  function main (line 18) | int main() {

FILE: basic_content/static/static_error_variable.cpp
  class Apple (line 6) | class Apple {
    method Apple (line 10) | Apple(){
  function main (line 15) | int main() {

FILE: basic_content/static/static_funciton.cpp
  class Apple (line 4) | class Apple {
    method printMsg (line 7) | static void printMsg() { cout << "Welcome to Apple!"; }
  function main (line 11) | int main() {

FILE: basic_content/static/static_variable.cpp
  class GfG (line 6) | class GfG {
    method GfG (line 10) | GfG(){
  function main (line 17) | int main() {

FILE: basic_content/struct/ext_struct_func.cpp
  type Base (line 4) | struct Base {
    method print (line 11) | virtual void print() { printf("%s\n", "Base"); }
    method Base (line 12) | Base() { cout << "Base construct" << endl; }
  type Derived (line 16) | struct Derived : Base {
    method Derived (line 18) | Derived() { cout << "Derived construct" << endl; }
    method print (line 23) | void print() { printf("%s\n", "Derived"); }
  function main (line 26) | int main() {

FILE: basic_content/struct/struct_func.c
  type Base (line 3) | struct Base
  function Base (line 15) | void Base()
  function main (line 22) | int main()

FILE: basic_content/struct/struct_func.cpp
  type Base (line 4) | struct Base {
    method print (line 11) | void print() { printf("%s\n", "hello world"); }
  function main (line 14) | int main() {

FILE: basic_content/struct/struct_func_func.cpp
  type Base (line 4) | struct Base {
    method print (line 11) | void print() { printf("%s\n", "hello world"); }
  type Base1 (line 14) | struct Base1 {
    method print (line 21) | void print() { printf("%s\n", "hello world"); }
  function Base (line 23) | void Base() { printf("%s\n", "I am Base func"); }
    method print (line 11) | void print() { printf("%s\n", "hello world"); }
  function main (line 25) | int main() {

FILE: basic_content/this/person.cpp
  class Person (line 5) | class Person {
    method Person (line 8) | Person(char *n, int a, SexType s) {
    method get_age (line 14) | int get_age() const { return this->age; }
    method Person (line 15) | Person &add_age(int a) {
  function main (line 27) | int main() {

FILE: basic_content/union/union.cpp
  function UnionTest (line 17) | UnionTest() : i(10) { print(i); }
  function print (line 22) | void print(int i) { std::cout << i << std::endl; }
  function main (line 32) | int main() {

FILE: basic_content/using/derived_base.cpp
  class Base1 (line 5) | class Base1 {
    method Base1 (line 7) | Base1() : value(10) {}
    method test1 (line 9) | void test1() { cout << "Base test1..." << endl; }
  class Derived1 (line 15) | class Derived1 : Base1 {
    method test2 (line 17) | void test2() { cout << "value is " << value << endl; }
  class Base (line 20) | class Base {
    method Base (line 22) | Base() : value(20) {}
    method test1 (line 24) | void test1() { cout << "Base test1..." << endl; }
  class Derived (line 35) | class Derived : Base {
    method test2 (line 38) | void test2() { cout << "value is " << value << endl; }
  function main (line 41) | int main() {

FILE: basic_content/using/using_derived.cpp
  class Base (line 12) | class Base {
    method f (line 14) | void f() { cout << "f()" << endl; }
    method f (line 15) | void f(int n) { cout << "Base::f(int)" << endl; }
  class Derived (line 18) | class Derived : private Base {
    method f (line 21) | void f(int n) { cout << "Derived::f(int)" << endl; }
  function main (line 24) | int main() {

FILE: basic_content/using/using_global.cpp
  function func (line 13) | void func() { cout << "::func" << endl; }
  type ns1 (line 15) | namespace ns1 {
    function func (line 16) | void func() { cout << "ns1::func" << endl; }
  type ns2 (line 19) | namespace ns2 {
    function func (line 25) | void func() { cout << "other::func" << endl; }
  function main (line 29) | int main() {

FILE: basic_content/using/using_typedef.cpp
  function main (line 17) | int main() {

FILE: basic_content/virtual/set1/emp.cpp
  class Employee (line 4) | class Employee {
    method raiseSalary (line 6) | virtual void raiseSalary() { cout << 0 << endl; }
    method promote (line 8) | virtual void promote() { /* common promote code */
  class Manager (line 12) | class Manager : public Employee {
    method raiseSalary (line 13) | virtual void raiseSalary() { cout << 100 << endl; }
    method promote (line 15) | virtual void promote() { /* Manager specific promote */
  class Engineer (line 18) | class Engineer : public Employee {
    method raiseSalary (line 19) | virtual void raiseSalary() { cout << 200 << endl; }
    method promote (line 21) | virtual void promote() { /* Manager specific promote */
  function globalRaiseSalary (line 30) | void globalRaiseSalary(Employee *emp[], int n) {
  function main (line 36) | int main() {

FILE: basic_content/virtual/set2/default_arg.cpp
  class Base (line 13) | class Base {
    method fun (line 15) | virtual void fun(int x = 10) { cout << "Base::fun(), x = " << x << end...
  class Derived (line 18) | class Derived : public Base {
    method fun (line 20) | virtual void fun(int x = 20) { cout << "Derived::fun(), x = " << x << ...
  function main (line 23) | int main() {

FILE: basic_content/virtual/set3/copy_consrtuct.cpp
  class Base (line 4) | class Base {
  class Derived (line 8) | class Derived : public Base {
    method Derived (line 10) | Derived() { cout << "Derived created" << endl; }
    method Derived (line 12) | Derived(const Derived &rhs) {
  function main (line 19) | int main() {

FILE: basic_content/virtual/set3/full_virde.cpp
  class base (line 17) | class base {
    method base (line 19) | base() { cout << "Constructing base \n"; }
  class derived (line 23) | class derived : public base {
    method derived (line 25) | derived() { cout << "Constructing derived \n"; }
  function main (line 29) | int main(void) {

FILE: basic_content/virtual/set3/inline_virtual.cpp
  class Base (line 3) | class Base {
    method who (line 5) | inline virtual void who() { cout << "I am Base\n"; }
  class Derived (line 8) | class Derived : public Base {
    method who (line 10) | inline void who() // 不写inline时隐式内联
  function main (line 16) | int main() {

FILE: basic_content/virtual/set3/static_error.cpp
  function fun (line 12) | virtual static void fun() {}
  function fun (line 13) | static void fun() const {}

FILE: basic_content/virtual/set3/vir_con.cpp
  class Base (line 30) | class Base {
    method Base (line 32) | Base() {}
  class Derived1 (line 46) | class Derived1 : public Base {
    method Derived1 (line 48) | Derived1() { cout << "Derived1 created" << endl; }
    method Derived1 (line 50) | Derived1(const Derived1 &rhs) {
    method ChangeAttributes (line 56) | void ChangeAttributes() { cout << "Derived1 Attributes Changed" << end...
    method Base (line 58) | Base *Clone() { return new Derived1(*this); }
  class Derived2 (line 61) | class Derived2 : public Base {
    method Derived2 (line 63) | Derived2() { cout << "Derived2 created" << endl; }
    method Derived2 (line 65) | Derived2(const Derived2 &rhs) {
    method ChangeAttributes (line 71) | void ChangeAttributes() { cout << "Derived2 Attributes Changed" << end...
    method Base (line 73) | Base *Clone() { return new Derived2(*this); }
  class Derived3 (line 76) | class Derived3 : public Base {
    method Derived3 (line 78) | Derived3() { cout << "Derived3 created" << endl; }
    method Derived3 (line 80) | Derived3(const Derived3 &rhs) {
    method ChangeAttributes (line 86) | void ChangeAttributes() { cout << "Derived3 Attributes Changed" << end...
    method Base (line 88) | Base *Clone() { return new Derived3(*this); }
  function Base (line 93) | Base *Base::Create(int id) {
    method Base (line 32) | Base() {}
  class User (line 108) | class User {
    method User (line 110) | User() : pBase(0) {
    method Action (line 134) | void Action() {
  function main (line 152) | int main() {

FILE: basic_content/virtual/set3/vir_de.cpp
  class base (line 19) | class base {
    method base (line 21) | base() { cout << "Constructing base \n"; }
  class derived (line 25) | class derived : public base {
    method derived (line 27) | derived() { cout << "Constructing derived \n"; }
  function main (line 31) | int main(void) {

FILE: basic_content/virtual/set3/virtual_function.cpp
  class Derived (line 16) | class Derived
    method fun (line 26) | void fun() { cout << "Derived Fun"; }
  class Base (line 18) | class Base {
    method fun (line 20) | virtual void fun() { cout << "Base Fun"; }
  class Derived (line 24) | class Derived : public Base {
    method fun (line 26) | void fun() { cout << "Derived Fun"; }
  function main (line 29) | int main() {

FILE: basic_content/virtual/set3/virtual_function1.cpp
  class Derived (line 4) | class Derived
    method fun (line 14) | void fun() { cout << "Derived Fun"; }
  class Base (line 6) | class Base {
    method fun (line 8) | virtual void fun() { cout << "Base Fun"; }
  class Derived (line 12) | class Derived : public Base {
    method fun (line 14) | void fun() { cout << "Derived Fun"; }
  function main (line 17) | int main() {

FILE: basic_content/virtual/set3/virtual_inline.cpp
  class Base (line 13) | class Base {
    method who (line 15) | virtual void who() { cout << "I am Base\n"; }
  class Derived (line 17) | class Derived : public Base {
    method who (line 19) | void who() { cout << "I am Derived\n"; }
  function main (line 22) | int main() {

FILE: basic_content/virtual/set4/rtti.cpp
  class B (line 17) | class B {
    method fun (line 18) | virtual void fun() {}
  class D (line 20) | class D : public B {}
  function main (line 22) | int main() {

FILE: basic_content/virtual/set4/warn_rtti.cpp
  class A (line 5) | class A {}
  class B (line 9) | class B {
  class D (line 17) | class D : public A {}
  class E (line 21) | class E : private A {}
  class F (line 25) | class F : private B {}

FILE: basic_content/volatile/noopt_vola.cpp
  function main (line 3) | int main(void) {

FILE: basic_content/volatile/volatile.cpp
  function main (line 4) | int main(void) {

FILE: basic_content/vptr_vtable/vptr1.cpp
  class Base (line 13) | class Base {
    method Base (line 15) | Base(){}
    method fun1 (line 16) | virtual void fun1() { cout << "Base::fun1()" << endl; }
    method fun2 (line 17) | virtual void fun2() { cout << "Base::fun2()" << endl; }
    method fun3 (line 18) | virtual void fun3() {}
  class Derived (line 25) | class Derived : public Base {
    method Derived (line 27) | Derived(){}
    method fun1 (line 28) | void fun1() { cout << "Derived::fun1()" << endl; }
    method fun2 (line 29) | void fun2() { cout << "DerivedClass::fun2()" << endl; }
  function Fun (line 42) | Fun getAddr(void *obj, unsigned int offset) {
  function main (line 58) | int main(void) {

FILE: codingStyleIdioms/1_classInitializers/1.1_nest.cpp
  class Animal (line 8) | class Animal {
    method Animal (line 10) | Animal() {
    method Animal (line 14) | Animal(const Animal &) {
    method Animal (line 18) | Animal &operator=(const Animal &) {
  class Dog (line 28) | class Dog {
    method Dog (line 31) | Dog(const Animal &animal) : __animal(animal) {
  function main (line 47) | int main() {

FILE: codingStyleIdioms/1_classInitializers/1.2_nodefault_ctor.cpp
  class Animal (line 6) | class Animal {
    method Animal (line 8) | Animal(int age) {
    method Animal (line 12) | Animal(const Animal & animal) {
    method Animal (line 16) | Animal &operator=(const Animal & amimal) {
  class Dog (line 27) | class Dog : Animal {
    method Dog (line 29) | Dog(int age) : Animal(age) {
  function main (line 38) | int main() {

FILE: codingStyleIdioms/1_classInitializers/1.3_const.cpp
  class Animal (line 8) | class Animal {
    method Animal (line 10) | Animal(int& age,std::string name):age_(age),name_(name) {
  function main (line 18) | int main() {

FILE: codingStyleIdioms/1_classInitializers/initializer.cpp
  class A (line 10) | class A {
    method A (line 12) | A(int a) : _a(a), _p(nullptr) {     // 初始化列表
  function main (line 21) | int main() {

FILE: codingStyleIdioms/2_enumclass/namespace.cpp
  type EntityType (line 9) | namespace EntityType {
    type Enum (line 10) | enum Enum {
  function foo (line 18) | void foo(EntityType::Enum entityType)
  type EntityType1 (line 26) | enum class EntityType1 {
  function foo (line 33) | void foo(EntityType1 entityType)
  function main (line 40) | int main() {

FILE: codingStyleIdioms/3_RAII/RAII.cpp
  type shape_type (line 7) | enum class shape_type {
  class shape (line 14) | class shape {
    method shape (line 16) | shape() { cout << "shape" << endl; }
    method print (line 18) | virtual void print() {
  class circle (line 25) | class circle : public shape {
    method circle (line 27) | circle() { cout << "circle" << endl; }
    method print (line 29) | void print() {
  class triangle (line 34) | class triangle : public shape {
    method triangle (line 36) | triangle() { cout << "triangle" << endl; }
    method print (line 38) | void print() {
  class rectangle (line 43) | class rectangle : public shape {
    method rectangle (line 45) | rectangle() { cout << "rectangle" << endl; }
    method print (line 47) | void print() {
  function shape (line 53) | shape *create_shape(shape_type type) {
    method shape (line 16) | shape() { cout << "shape" << endl; }
    method print (line 18) | virtual void print() {
  class shape_wrapper (line 64) | class shape_wrapper {
    method shape_wrapper (line 66) | explicit shape_wrapper(shape *ptr = nullptr) : ptr_(ptr) {}
    method shape (line 72) | shape *get() const {
  function foo (line 81) | void foo() {
  function main (line 86) | int main() {

FILE: codingStyleIdioms/3_RAII/RAII_fstram.cpp
  function foo (line 12) | void foo() {
  function main (line 23) | int main() {

FILE: codingStyleIdioms/3_RAII/c++_example.cpp
  function main (line 5) | int main() {

FILE: codingStyleIdioms/3_RAII/c++_example1.cpp
  function read_lines_from_file (line 10) | vector<string> read_lines_from_file(string &file_name) {
  function main (line 54) | int main() {

FILE: codingStyleIdioms/3_RAII/c++_example2.cpp
  function read_lines_from_file (line 11) | unique_ptr<vector<string>> read_lines_from_file(string &file_name) {
  function main (line 25) | int main() {

FILE: codingStyleIdioms/3_RAII/c_example.cpp
  function main (line 7) | int main() {

FILE: codingStyleIdioms/4_copy-swap/copy-swapAndADL.cpp
  type A (line 9) | namespace A {
    class smart_ptr (line 11) | class smart_ptr {
      method smart_ptr (line 13) | smart_ptr() noexcept : ptr_(new T()) {
      method smart_ptr (line 17) | smart_ptr(const T &ptr) noexcept : ptr_(new T(ptr)) {
      method smart_ptr (line 21) | smart_ptr(smart_ptr &rhs) noexcept {
      method smart_ptr (line 51) | smart_ptr &operator=(smart_ptr rhs) noexcept {
      method smart_ptr (line 56) | smart_ptr(smart_ptr &&rhs) noexcept {
      method swap (line 71) | void swap(smart_ptr &rhs) noexcept { // noexcept == throw() 保证不抛出异常
      method T (line 76) | T *release() noexcept {
      method T (line 82) | T *get() const noexcept {
    function swap (line 92) | void swap(A::smart_ptr<T> &lhs, A::smart_ptr<T> &rhs) noexcept {
  function main (line 106) | int main() {

FILE: codingStyleIdioms/5_pImpl/noPimpl.cpp
  class C (line 5) | class C {
  class D (line 9) | class D {
  class X (line 13) | class X {
  function main (line 20) | int main() {

FILE: codingStyleIdioms/5_pImpl/pimpl.cpp
  class private_foo (line 10) | class private_foo
    method bar (line 25) | void bar() {
  class foo (line 11) | class foo {
  class private_foo (line 23) | class private_foo {
    method bar (line 25) | void bar() {
  function main (line 45) | int main() {

FILE: codingStyleIdioms/5_pImpl/pimplTime.cpp
  class C (line 5) | class C {
  class D (line 9) | class D {
  class X (line 13) | class X {
    type XImpl (line 15) | struct XImpl
  type X::XImpl (line 19) | struct X::XImpl {
  function main (line 24) | int main() {

FILE: codingStyleIdioms/5_pImpl/pimplTime.h
  function class (line 5) | class C {
  function class (line 9) | class D {
  function class (line 13) | class X {

FILE: concurrency/Threading_In_CPlusPlus/1.thread/intro.cpp
  function findEven (line 15) | void findEven(ull start, ull end) {
  function findOdd (line 21) | void findOdd(ull start, ull end) {
  function main (line 27) | int main() {

FILE: concurrency/Threading_In_CPlusPlus/1.thread/thread.cpp
  function findEven (line 25) | void findEven(ull start, ull end) {
  function findOdd (line 31) | void findOdd(ull start, ull end) {
  function main (line 37) | int main() {

FILE: concurrency/Threading_In_CPlusPlus/2.create_type/1.function_pointer.cpp
  function fun (line 11) | void fun(int x) {
  function main (line 17) | int main() {

FILE: concurrency/Threading_In_CPlusPlus/2.create_type/2.lambda_function.cpp
  function main (line 12) | int main() {

FILE: concurrency/Threading_In_CPlusPlus/2.create_type/3.functor.cpp
  class Base (line 12) | class Base {
  function main (line 21) | int main() {

FILE: concurrency/Threading_In_CPlusPlus/2.create_type/4.no_static_member_function.cpp
  class Base (line 12) | class Base {
    method fun (line 14) | void fun(int x) {
  function main (line 21) | int main() {

FILE: concurrency/Threading_In_CPlusPlus/2.create_type/5.static_member_function.cpp
  class Base (line 12) | class Base {
    method fun (line 14) | static void fun(int x) {
  function main (line 21) | int main() {

FILE: concurrency/Threading_In_CPlusPlus/3.join_detach/detach.cpp
  function run (line 19) | void run(int count) {
  function main (line 26) | int main() {

FILE: concurrency/Threading_In_CPlusPlus/3.join_detach/join.cpp
  function run (line 19) | void run(int count) {
  function main (line 26) | int main() {

FILE: concurrency/Threading_In_CPlusPlus/4.mutex/an_example_of_bank_account.cpp
  class BankAccount (line 8) | class BankAccount {
    method BankAccount (line 10) | BankAccount() : balance(0) {}
    method deposit (line 13) | void deposit(int amount) {
    method withdraw (line 19) | void withdraw(int amount) {
    method get_balance (line 29) | int get_balance() const {
  function deposit_to_account (line 38) | void deposit_to_account(BankAccount& account) {
  function withdraw_from_account (line 44) | void withdraw_from_account(BankAccount& account) {
  function main (line 50) | int main() {

FILE: concurrency/Threading_In_CPlusPlus/4.mutex/critical_section.cpp
  function main (line 24) | int main() {

FILE: concurrency/concurrency_v1/chapter1/1_helloworld.cpp
  function hello (line 11) | void hello() {
  function main (line 15) | int main() {

FILE: concurrency/concurrency_v1/chapter2/2.1_basic.cpp
  class background_task (line 12) | class background_task {
  function do_something (line 19) | void do_something(int &i) {
  type func (line 23) | struct func {
    method func (line 26) | func(int &i_) : i(i_) {}
  function f (line 36) | void f() {
  class thread_guard (line 55) | class thread_guard {
    method thread_guard (line 58) | explicit thread_guard(std::thread &t_) :
    method thread_guard (line 68) | thread_guard(thread_guard const &) = delete;
    method thread_guard (line 69) | thread_guard &operator=(thread_guard const &) = delete;
  function f1 (line 71) | void f1()
  function main (line 84) | int main() {

FILE: concurrency/concurrency_v1/chapter2/2.2_transfer.cpp
  class X (line 9) | class X {
  function process_big_object (line 14) | void process_big_object(std::unique_ptr<X>)
  function main (line 19) | int main() {

FILE: concurrency/concurrency_v1/chapter2/2.3_ownership.cpp
  function some_function (line 13) | void some_function() {}
  function some_other_function (line 15) | void some_other_function() {}
  function do_something (line 23) | void do_something(int i) {
  type func (line 27) | struct func {
    method func (line 30) | func(int &i_) : i(i_) {}
  class scoped_thread (line 39) | class scoped_thread {
    method scoped_thread (line 42) | explicit scoped_thread(std::thread t_) :                 // 1
    method scoped_thread (line 52) | scoped_thread(scoped_thread const &) = delete;
    method scoped_thread (line 54) | scoped_thread &operator=(scoped_thread const &) = delete;
  function do_work (line 57) | void do_work(unsigned id) {}
  function f (line 59) | void f() {
  function main (line 68) | int main() {

FILE: concurrency/concurrency_v1/chapter2/2.4_runtime.cpp
  type accumulate_block (line 15) | struct accumulate_block {
  function T (line 22) | T parallel_accumlate(Iterator first, Iterator last, T init) {
  function main (line 55) | int main() {

FILE: concurrency/concurrency_v1/chapter2/2_5_id.cpp
  function do_master_thread_work (line 14) | void do_master_thread_work() {
  function do_common_work (line 18) | void do_common_work() {
  function some_core_part_of_algorithm (line 22) | void some_core_part_of_algorithm() {
  function main (line 29) | int main() {

FILE: cpp2.0/cpp11/alias.cpp
  function main (line 14) | int main() {

FILE: cpp2.0/cpp11/auto.cpp
  class C (line 34) | class C {
    method C (line 36) | explicit C(const string &s) : mystr(s) {
    method ostream (line 40) | ostream &operator<<(ostream out, const C &c) {
  function main (line 48) | int main() {

FILE: cpp2.0/cpp11/constexpr.cpp
  function foo (line 21) | constexpr int foo(int i)
  function main (line 26) | int main()

FILE: cpp2.0/cpp11/decltype.cpp
  function add (line 19) | auto add(T1 x, T2 y) -> decltype(x + y)
  class Person (line 24) | class Person
  function main (line 30) | int main()

FILE: cpp2.0/cpp11/default_delete.cpp
  class Zoo (line 10) | class Zoo {
    method Zoo (line 13) | Zoo(int a, int b) : a(a), b(b) {
    method Zoo (line 17) | Zoo() = default;
    method Zoo (line 19) | Zoo(const Zoo &) = delete;
    method Zoo (line 21) | Zoo(Zoo &&) = default;
    method Zoo (line 23) | Zoo &operator=(const Zoo &) = default;
    method Zoo (line 25) | Zoo &operator=(const Zoo &&) = delete;
    method fun1 (line 29) | void fun1() = delete;
  class Empty (line 41) | class Empty {
  class Empty1 (line 45) | class Empty1 {
    method Empty1 (line 47) | Empty1() {}
    method Empty1 (line 49) | Empty1(const Empty1 &rhs) {}
  type NoCopy (line 56) | struct NoCopy {
    method NoCopy (line 57) | NoCopy() = default;
    method NoCopy (line 59) | NoCopy(const NoCopy &) = delete;
    method NoCopy (line 61) | NoCopy &operator=(const NoCopy &) = delete;
  type NoDtor (line 67) | struct NoDtor {
    method NoDtor (line 68) | NoDtor() = default;
  class PrivateCopy (line 75) | class PrivateCopy {
    method PrivateCopy (line 77) | PrivateCopy(const PrivateCopy &) {}
    method PrivateCopy (line 82) | PrivateCopy() = default;
  class Foo (line 88) | class Foo : public PrivateCopy {
  function main (line 92) | int main() {

FILE: cpp2.0/cpp11/explicit.cpp
  class Fraction (line 10) | class Fraction
    method Fraction (line 14) | Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den) {}
    method Fraction (line 16) | Fraction operator+(const Fraction &f)
    method getNumAndDen (line 21) | void getNumAndDen()
  class Fraction1 (line 32) | class Fraction1
    method Fraction1 (line 36) | explicit Fraction1(int num, int den = 1) : m_numerator(num), m_denomin...
    method Fraction1 (line 38) | Fraction1 operator+(const Fraction1 &f)
    method getNumAndDen (line 43) | void getNumAndDen()
  class P (line 53) | class P
    method P (line 56) | P(int a, int b)
    method P (line 61) | P(int a, int b, int c)
    method P (line 65) | explicit P(int a, int b, int c, int d)
  function fp (line 71) | void fp(const P &)
  function main (line 75) | int main()

FILE: cpp2.0/cpp11/final.cpp
  class Base (line 11) | class Base final {
    method Base (line 13) | Base() {}
    method func (line 15) | virtual void func() {}
  class Derivered (line 18) | class Derivered : public Base {     // error: cannot derive from ‘final’...
  class Base1 (line 21) | class Base1 {
    method Base1 (line 23) | Base1() {}
    method func (line 25) | virtual void func() final {}
  class Derivered1 (line 28) | class Derivered1 : public Base1 {
    method func (line 29) | virtual void func() {}
  function main (line 31) | int main() {

FILE: cpp2.0/cpp11/hash.cpp
  class Customer (line 12) | class Customer {
  class CustomerHash (line 17) | class CustomerHash {
  function customer_hash_func (line 25) | size_t customer_hash_func(const Customer &t) {
  type std (line 29) | namespace std {     // 必须放在std里面
    type hash<Customer> (line 31) | struct hash<Customer> : public __hash_base<size_t, Customer> {      //...
  function hash_combine (line 44) | inline void hash_combine(size_t& seed, const T& val){
  function hash_val (line 51) | inline void hash_val(size_t& seed, const T& val){
  function hash_val (line 57) | inline void hash_val(size_t& seed, const T& val, const Types&... args){
  function hash_val (line 63) | inline size_t hash_val(const Types&... args){
  function main (line 70) | int main() {

FILE: cpp2.0/cpp11/initializer.cpp
  function main (line 9) | int main() {

FILE: cpp2.0/cpp11/lambda.cpp
  class UnNamedLocalFunction (line 20) | class UnNamedLocalFunction {
    method UnNamedLocalFunction (line 24) | UnNamedLocalFunction(int var) : localVar(var) {}
  class Person (line 31) | class Person {
  class LambdaFunctor (line 37) | class LambdaFunctor {
    method LambdaFunctor (line 39) | LambdaFunctor(int a, int b) : m_a(a), m_b(b) {}
  class X (line 50) | class X {
    method X (line 54) | X(int x, int y) : __x(x), __y(y) {}
    method f (line 58) | int f() {
    method ff (line 68) | int ff() {
  function main (line 75) | int main() {

FILE: cpp2.0/cpp11/move.cpp
  class MyStringNoMove (line 18) | class MyStringNoMove {
    method _init_data (line 31) | void _init_data(const char *s) {
    method MyStringNoMove (line 37) | MyStringNoMove() : _data(NULL), _len(0) { ++DCtor; }
    method MyStringNoMove (line 39) | MyStringNoMove(const char *p) : _len(strlen(p)) {
    method MyStringNoMove (line 45) | MyStringNoMove(const MyStringNoMove &str) : _len(str._len) {
    method MyStringNoMove (line 52) | MyStringNoMove &operator=(const MyStringNoMove &str) {
  class MyString (line 94) | class MyString {
    method _init_data (line 107) | void _init_data(const char *s) {
    method MyString (line 113) | MyString() : _data(NULL), _len(0) { ++DCtor; }
    method MyString (line 115) | MyString(const char *p) : _len(strlen(p)) {
    method MyString (line 121) | MyString(const MyString &str) : _len(str._len) {
    method MyString (line 127) | MyString(MyString &&str) noexcept: _data(str._data), _len(str._len) {
    method MyString (line 134) | MyString &operator=(const MyString &str) {
    method MyString (line 147) | MyString &operator=(MyString &&str) {
  type std (line 189) | namespace std {
    type hash<MyStringNoMove> (line 191) | struct hash<MyStringNoMove> : public __hash_base<size_t, MyStringNoMov...
    type hash<MyString> (line 199) | struct hash<MyString> : public __hash_base<size_t, MyString> {
  function output_static_data (line 208) | void output_static_data(const T &myStr) {
  function test_moveable (line 222) | void test_moveable(M c1, NM c2, long &value) {
  function main (line 274) | int main() {

FILE: cpp2.0/cpp11/noexcept.cpp
  function foo (line 19) | void foo() noexcept(true) {
  function main (line 22) | int main() {

FILE: cpp2.0/cpp11/nullptr.cpp
  function f (line 8) | void f(int i) {
  function f (line 12) | void f(void *p) {
  function main (line 15) | int main() {

FILE: cpp2.0/cpp11/override.cpp
  class Base (line 9) | class Base
    method Base (line 12) | Base() {}
    method func (line 13) | virtual void func() {}
  class Derivered (line 15) | class Derivered : public Base
    method func (line 17) | virtual void func(int) override {}
  function main (line 24) | int main()

FILE: cpp2.0/cpp11/rvalue.cpp
  function foo (line 13) | int foo() { return 5; }
  class Foo (line 15) | class Foo {
    method Foo (line 17) | Foo() = default;
    method Foo (line 19) | Foo(const Foo &foo) = default;
    method Foo (line 21) | Foo(Foo &&foo) noexcept {}
  function process (line 26) | void process(int &i) {
  function process (line 30) | void process(int &&i) {
  function UnPerfectForward (line 34) | void UnPerfectForward(int &&i) {
  function PerfectForward (line 39) | void PerfectForward(int &&i) {
  function main (line 45) | int main() {

FILE: cpp2.0/cpp11/template_template.cpp
  class XCls (line 11) | class XCls {
  function main (line 20) | int main() {

FILE: cpp2.0/cpp11/tuple.cpp
  function main (line 11) | int main() {

FILE: cpp2.0/cpp11/type_alias.cpp
  function example (line 15) | void example(int, int) {}
  type Container (line 19) | struct Container {
  function func2 (line 24) | void func2(const Cn &cn) {
  function main (line 42) | int main() {

FILE: cpp2.0/cpp11/uniform_initialization.cpp
  function main (line 10) | int main() {

FILE: cpp2.0/cpp11/variadic/variadic.cpp
  function _hash (line 17) | void _hash(size_t &seed, const T &val) {
  function _hash (line 24) | void _hash(size_t &seed, const T& val,const Args &... args) {
  function _hash (line 33) | size_t _hash(const Args &... args) {
  class A (line 43) | class A {
    method A (line 47) | A() {
  function main (line 53) | int main(void) {

FILE: cpp2.0/cpp11/variadic/variadic1.cpp
  function printX (line 11) | void printX() {
  function printX (line 17) | void printX(const T &firstArg, const Type &...args) {
  function printX (line 24) | void printX(const Type &...args) {
  function main (line 29) | int main() {

FILE: cpp2.0/cpp11/variadic/variadic2.cpp
  function print (line 9) | void print(const char *s) {
  function print (line 18) | void print(const char *s, T value, Args... args) {
  function main (line 30) | int main() {

FILE: cpp2.0/cpp11/variadic/variadic3_4.cpp
  function max (line 10) | int max(initializer_list<int> initializerList) {
  function maximum (line 19) | int maximum(int n) {
  function maximum (line 24) | int maximum(int n, Args...args) {
  function main (line 28) | int main() {

FILE: cpp2.0/cpp11/variadic/variadic5.cpp
  type print_tuple (line 20) | struct print_tuple {
    method print (line 21) | static void print(ostream &os, const tuple<Args...> &t) {
  type print_tuple<MAX, MAX, Args...> (line 29) | struct print_tuple<MAX, MAX, Args...> {
    method print (line 30) | static void print(ostream &os, const tuple<Args...> &t) {
  function ostream (line 35) | ostream &operator<<(ostream &os, const tuple<Args...> &t) {
  function main (line 42) | int main() {

FILE: cpp2.0/cpp11/variadic/variadic6.cpp
  type light (line 11) | namespace light {
    class tuple (line 13) | class tuple
    class tuple<> (line 16) | class tuple<> {
  class tuple<Head, Tail...> (line 20) | class tuple<Head, Tail...> : private tuple<Tail...> {
    method tuple (line 25) | tuple() {}
    method tuple (line 27) | tuple(Head h, Tail...tail) : m_head(h), inherited(tail...) {}
    method head (line 30) | auto head() -> decltype(m_head) { return m_head; }
    method inherited (line 33) | inherited &tail() { return *this; }
  function main (line 43) | int main() {

FILE: cpp2.0/cpp11/variadic/variadic7.cpp
  type light (line 9) | namespace light {
    class tuple (line 11) | class tuple
    class tuple<> (line 14) | class tuple<> {
  class tuple<Head, Tail...> (line 18) | class tuple<Head, Tail...> {
    method tuple (line 24) | tuple() {}
    method get (line 25) | int get() { return sizeof(composited);}
    method tuple (line 26) | tuple(Head h, Tail...tail) : m_head(h), m_tai(tail...) {}
    method head (line 29) | auto head() -> decltype(m_head) { return m_head; }
    method composited (line 32) | composited &tail() { return m_tai; }
  type A (line 43) | struct A {
  function main (line 47) | int main() {

FILE: design_pattern/producer_consumer/producer_consumer.cpp
  class BoundedBuffer (line 12) | class BoundedBuffer {
    method BoundedBuffer (line 14) | BoundedBuffer(size_t n) {
    method Produce (line 20) | void Produce(int n) {
    method Consume (line 36) | int Consume() {
  function Producer (line 66) | void Producer() {
  function Consumer (line 77) | void Consumer() {
  function main (line 88) | int main() {

FILE: design_pattern/singleton/barrier_singleton.cpp
  class singleton (line 23) | class singleton {
    method singleton (line 25) | singleton() {}
  function singleton (line 36) | singleton *singleton::instance() {
    method singleton (line 25) | singleton() {}

FILE: design_pattern/singleton/cpulpuls11_singleton.cpp
  class singleton (line 13) | class singleton {
    method singleton (line 15) | singleton() {}
  function singleton (line 32) | singleton *singleton::instance() {
    method singleton (line 15) | singleton() {}

FILE: design_pattern/singleton/dcl_singleton.cpp
  class singleton (line 10) | class singleton {
    method singleton (line 12) | singleton() {}
    class CGarbo (line 21) | class CGarbo {
  function singleton (line 36) | singleton *singleton::instance() {
    method singleton (line 12) | singleton() {}
    class CGarbo (line 21) | class CGarbo {

FILE: design_pattern/singleton/hungrysingleton.cpp
  class singleton (line 5) | class singleton {
    method singleton (line 7) | singleton() {}
  function singleton (line 15) | singleton *singleton::instance() { return p; }
    method singleton (line 7) | singleton() {}

FILE: design_pattern/singleton/iazysingleton.cpp
  class singleton (line 5) | class singleton {
    method singleton (line 7) | singleton() {}
  function singleton (line 16) | singleton *singleton::instance() {
    method singleton (line 7) | singleton() {}

FILE: design_pattern/singleton/lock_singleton.cpp
  class singleton (line 9) | class singleton {
    method singleton (line 11) | singleton() {}
  function singleton (line 21) | singleton *singleton::instance() {
    method singleton (line 11) | singleton() {}

FILE: design_pattern/singleton/pthreadoncesingleton.cpp
  class singleton (line 8) | class singleton {
    method init (line 14) | static void init() { p = new singleton(); }
    method singleton (line 19) | singleton *instance() {

FILE: design_pattern/singleton/static_local_singleton.cpp
  class singleton (line 11) | class singleton {
    method singleton (line 13) | singleton() {}
  function singleton (line 19) | singleton &singleton::instance() {
    method singleton (line 13) | singleton() {}

FILE: effective_cpp/2.cpp
  type A (line 8) | struct A {
  class C (line 12) | class C {
    type con (line 17) | enum con {
  function Max (line 24) | inline int Max(const T& a, const T& b){
  function main (line 28) | int main() {

FILE: english/basic_content/abstract/abstract.cpp
  class A (line 13) | class A {
    method g (line 16) | void g(){ this->f(); }
    method A (line 17) | A(){}
  class B (line 19) | class B:public A{
    method f (line 21) | void f(){ cout<<"B:f()"<<endl;}
  function main (line 23) | int main(){

FILE: english/basic_content/abstract/derived_full.cpp
  class Base (line 12) | class Base
    method getX (line 17) | int getX() { return x; }
  class Derived (line 20) | class Derived: public Base
    method fun (line 24) | void fun() { cout << "fun() called"; }
  function main (line 27) | int main(void)

FILE: english/basic_content/abstract/interesting_facts1.cpp
  class Test (line 15) | class Test
    method getX (line 20) | int getX() { return x; }
  function main (line 23) | int main(void)

FILE: english/basic_content/abstract/interesting_facts2.cpp
  class Base (line 16) | class Base
    method getX (line 21) | int getX() { return x; }
  class Derived (line 24) | class Derived: public Base
    method show (line 27) | void show() { cout << "In Derived \n"; }
    method Derived (line 28) | Derived(){}
  function main (line 30) | int main(void)

FILE: english/basic_content/abstract/interesting_facts3.cpp
  class Base (line 12) | class Base
    method getX (line 17) | int getX() { return x; }
  class Derived (line 19) | class Derived: public Base
  function main (line 24) | int main(void)

FILE: english/basic_content/abstract/interesting_facts4.cpp
  class Base (line 13) | class Base
    method Base (line 19) | Base(int i) { x = i; }
  class Derived (line 22) | class Derived: public Base
    method Derived (line 26) | Derived(int i, int j):Base(i) { y = j; }
    method fun (line 27) | void fun() { cout << "x = " << x << ", y = " << y; }
  function main (line 30) | int main(void)

FILE: english/basic_content/abstract/interesting_facts5.cpp
  class Base (line 13) | class Base  {
    method Base (line 15) | Base()    { cout << "Constructor: Base" << endl; }
  class Derived (line 19) | class Derived: public Base {
    method Derived (line 21) | Derived()   { cout << "Constructor: Derived" << endl; }
  function main (line 25) | int main()  {

FILE: english/basic_content/abstract/pure_virtual.cpp
  class A (line 14) | class A
  function main (line 23) | int main()

FILE: english/basic_content/abstract/test.cpp
  class Test (line 15) | class Test

FILE: english/basic_content/assert/assert.c
  function main (line 4) | int main()

FILE: english/basic_content/assert/ignore_assert.c
  function main (line 13) | int main(){

FILE: english/basic_content/bit/learn.cpp
  type stuff (line 4) | struct stuff
  function main (line 12) | int main(){

FILE: english/basic_content/c_poly/c++_examp.cpp
  class A (line 12) | class A
    method f (line 15) | virtual void f()//Implement a virtual function
  class B (line 21) | class B:public A    // 必须为共有继承,否则后面调用不到,class默认为私有继承!
    method f (line 24) | virtual void f()//Virtual function implementation, virtual keyword in ...
  function main (line 31) | int main()

FILE: english/basic_content/c_poly/c_examp.c
  type A (line 17) | typedef struct _A
  type B (line 26) | typedef struct _B
  function FunA (line 31) | void FunA()
  function FunB (line 36) | void FunB()
  function main (line 42) | int main()

FILE: english/basic_content/const/class_const/c++11_example/apple.cpp
  class Apple (line 1) | class Apple

FILE: english/basic_content/const/class_const/c++11_example/main.cpp
  function main (line 24) | int main(){

FILE: english/basic_content/const/class_const/first_example/apple.cpp
  class Apple (line 1) | class Apple

FILE: english/basic_content/const/class_const/first_example/main.cpp
  function main (line 25) | int main(){

FILE: english/basic_content/const/class_const/overload_example/apple.cpp
  class Apple (line 1) | class Apple

FILE: english/basic_content/const/class_const/overload_example/main.cpp
  function main (line 25) | int main(){

FILE: english/basic_content/const/class_const/static_example/apple.cpp
  class Apple (line 1) | class Apple

FILE: english/basic_content/const/class_const/static_example/main.cpp
  function main (line 26) | int main(){

FILE: english/basic_content/const/const_function.cpp
  function f (line 4) | void f(const int i){
  function main (line 9) | int main(){

FILE: english/basic_content/const/const_num.cpp
  function main (line 3) | int main(){

FILE: english/basic_content/const/extern_const/const_file2.cpp
  function main (line 8) | int main(){

FILE: english/basic_content/const/extern_const/file2.cpp
  function main (line 8) | int main(){

FILE: english/basic_content/const/funciton_const/condition1/condition1.cpp
  function main (line 5) | int main(){

FILE: english/basic_content/const/funciton_const/condition1/condition2.cpp
  function main (line 5) | int main(){

FILE: english/basic_content/const/funciton_const/condition1/condition3.cpp
  function main (line 4) | int main(){

FILE: english/basic_content/const/funciton_const/condition2/condition1.cpp
  function main (line 3) | int main(){

FILE: english/basic_content/const/funciton_const/condition2/condition2.cpp
  function main (line 3) | int main(){

FILE: english/basic_content/const/funciton_const/condition2/condition3.cpp
  function main (line 3) | int main(){

FILE: english/basic_content/const/funciton_const/condition3/condition1.cpp
  function main (line 4) | int main(){

FILE: english/basic_content/decltype/decltype.cpp
  function multiply (line 17) | auto multiply(T x, T y)->decltype(x*y)
  function main (line 22) | int main()

FILE: english/basic_content/enum/classic_practice.cpp
  type Color (line 14) | namespace Color
    type Type (line 16) | enum Type
  type Color1 (line 35) | struct Color1
    type Type (line 37) | enum Type
  type Color2 (line 49) | enum class Color2
  type Color3 (line 56) | enum class Color3:char
  type Color3 (line 59) | enum class Color3:char
  function main (line 65) | int main()

FILE: english/basic_content/enum/tradition_color.cpp
  type Color (line 4) | enum Color {RED,BLUE}
  type Feeling (line 5) | enum Feeling {EXCITED,BLUE}
  function main (line 7) | int main()

FILE: english/basic_content/explicit/explicit.cpp
  type A (line 5) | struct A
    method A (line 7) | A(int) { }
  type B (line 11) | struct B
    method B (line 13) | explicit B(int) {}
  function doA (line 17) | void doA(A a) {}
  function doB (line 19) | void doB(B b) {}
  function main (line 21) | int main()

FILE: english/basic_content/extern/extern_c++/add.c
  function add (line 3) | int add(int x,int y) {

FILE: english/basic_content/extern/extern_c++/add.cpp
  function main (line 6) | int main() {

FILE: english/basic_content/extern/extern_c/add.c
  function main (line 2) | int main() {

FILE: english/basic_content/extern/extern_c/add.cpp
  function add (line 3) | int add(int x,int y) {

FILE: english/basic_content/friend/friend_class.cpp
  class A (line 5) | class A
    method A (line 8) | A(int _a):a(_a){}
  class B (line 14) | class B
    method getb (line 17) | int getb(A ca) {
  function main (line 22) | int main()

FILE: english/basic_content/friend/friend_func.cpp
  class A (line 13) | class A
    method A (line 16) | A(int _a):a(_a){}
  function geta (line 22) | int geta(A &ca)
  function main (line 27) | int main()

FILE: english/basic_content/func_pointer/func_pointer.cpp
  function myfunc (line 22) | void myfunc(void)
  function glFun (line 27) | void glFun(int a){ cout<<a<<endl;}
  function main (line 28) | int main(){

FILE: english/basic_content/inline/inline.cpp
  function Foo (line 17) | inline int Foo(int x,int y) // 函数定义
  function main (line 41) | int main()

FILE: english/basic_content/inline/inline.h
  function class (line 2) | class A

FILE: english/basic_content/inline/inline_virtual.cpp
  class Base (line 3) | class Base
    method who (line 6) | inline virtual void who()
  class Derived (line 12) | class Derived : public Base
    method who (line 15) | inline void who()  // 不写inline时隐式内联
  function main (line 21) | int main()

FILE: english/basic_content/macro/do_while.cpp
  function f (line 15) | int f() {
  function ff (line 32) | int ff() {
  function fc (line 53) | int fc()
  function main (line 64) | int main() {

FILE: english/basic_content/macro/sig_examp.cpp
  function main (line 39) | int main() {

FILE: english/basic_content/maohao/maohao.cpp
  class A (line 6) | class A {
  function main (line 13) | int main() {

FILE: english/basic_content/pointer_refer/copy_construct.cpp
  class Copyable (line 13) | class Copyable {
    method Copyable (line 15) | Copyable(){}
    method Copyable (line 16) | Copyable(const Copyable &o) {
  function Copyable (line 20) | Copyable ReturnRvalue() {
    method Copyable (line 15) | Copyable(){}
    method Copyable (line 16) | Copyable(const Copyable &o) {
  function AcceptVal (line 23) | void AcceptVal(Copyable a) {
  function AcceptRef (line 26) | void AcceptRef(const Copyable& a) {
  function main (line 30) | int main() {

FILE: english/basic_content/pointer_refer/effec.cpp
  function test1 (line 3) | void test1(int* p)
  function test2 (line 9) | void test2(int& p)
  function main (line 15) | int main() {

FILE: english/basic_content/sizeof/blackclass.cpp
  class A (line 13) | class A{}
  function main (line 14) | int main()

FILE: english/basic_content/sizeof/genA.cpp
  class A (line 14) | class A
  function main (line 25) | int main()

FILE: english/basic_content/sizeof/geninhe.cpp
  class A (line 15) | class A
  class B (line 30) | class B:A
  class C (line 36) | class C
  class A1 (line 42) | class A1
    method fun (line 44) | virtual void fun(){}
  class C1 (line 46) | class C1:public A
  function main (line 51) | int main()

FILE: english/basic_content/sizeof/moreinhe.cpp
  class A (line 13) | class A
  class B (line 20) | class B
  class C (line 30) | class C:A,B
  function main (line 36) | int main()

FILE: english/basic_content/sizeof/morevir.cpp
  class A (line 13) | class A{
  function main (line 20) | int main()

FILE: english/basic_content/sizeof/static.cpp
  class A (line 12) | class A
  function main (line 24) | int main()

FILE: english/basic_content/sizeof/virinhe.cpp
  class A (line 13) | class A
    method fun (line 15) | virtual void fun() {}
  class B (line 18) | class B
    method fun2 (line 20) | virtual void fun2() {}
  class C (line 22) | class C : virtual public  A, virtual public B
    method fun3 (line 25) | virtual void fun3() {}
  function main (line 29) | int main()

FILE: english/basic_content/sizeof/virmoreinhe.cpp
  class A (line 13) | class A
    method fun (line 15) | virtual void fun() {}
  class B (line 18) | class B
    method fun2 (line 20) | virtual void fun2() {}
  class C (line 22) | class C : public  A, public B
    method fun3 (line 25) | virtual void fun3() {}
  function main (line 29) | int main()

FILE: english/basic_content/static/nostatic_class.cpp
  class Apple (line 4) | class Apple
    method Apple (line 8) | Apple()
  function main (line 19) | int main()

FILE: english/basic_content/static/static_class.cpp
  class Apple (line 4) | class Apple
    method Apple (line 8) | Apple()
  function main (line 19) | int main()

FILE: english/basic_content/static/static_demo.cpp
  function demo (line 7) | void demo()
  function main (line 19) | int main()

FILE: english/basic_content/static/static_error_variable.cpp
  class Apple (line 6) | class Apple
    method Apple (line 11) | Apple()
  function main (line 17) | int main()

FILE: english/basic_content/static/static_funciton.cpp
  class Apple (line 4) | class Apple
    method printMsg (line 8) | static void printMsg()
  function main (line 15) | int main()

FILE: english/basic_content/static/static_variable.cpp
  class GfG (line 6) | class GfG
    method GfG (line 11) | GfG()
  function main (line 19) | int main()

FILE: english/basic_content/struct/ext_struct_func.cpp
  type Base (line 4) | struct Base {
    method print (line 10) | virtual void print(){
    method Base (line 13) | Base(){cout<<"Base construct"<<endl;}
  type Derived (line 17) | struct Derived:Base {
    method Derived (line 19) | Derived(){cout<<"Derived construct"<<endl;}
    method print (line 23) | void print(){
  function main (line 28) | int main() {

FILE: english/basic_content/struct/struct_func.c
  type Base (line 3) | struct Base {            // public
  function Base (line 14) | void Base(){
  function main (line 20) | int main() {

FILE: english/basic_content/struct/struct_func.cpp
  type Base (line 4) | struct Base {
    method print (line 10) | void print(){
  function main (line 15) | int main() {

FILE: english/basic_content/struct/struct_func_func.cpp
  type Base (line 4) | struct Base {
    method print (line 10) | void print(){
  type Base1 (line 15) | struct Base1 {
    method print (line 21) | void print(){
  function Base (line 25) | void Base(){
    method print (line 10) | void print(){
  function main (line 29) | int main() {

FILE: english/basic_content/this/person.cpp
  class Person (line 6) | class Person{
    method Person (line 12) | Person(char *n, int a,SexType s){
    method get_age (line 18) | int get_age() const{
    method Person (line 22) | Person& add_age(int a){
  function main (line 36) | int main(){

FILE: english/basic_content/union/union.cpp
  function UnionTest (line 17) | UnionTest() : i(10) {print(i);}
  function print (line 21) | void print(int i){std::cout<<i<<std::endl;}
  function main (line 31) | int main() {

FILE: english/basic_content/using/derived_base.cpp
  class Base1 (line 5) | class Base1 {
    method Base1 (line 7) | Base1():value(10) {}
    method test1 (line 9) | void test1() { cout << "Base test1..." << endl; }
  class Derived1 (line 14) | class Derived1 : Base1 {
    method test2 (line 16) | void test2() { cout << "value is " << value << endl; }
  class Base (line 19) | class Base {
    method Base (line 21) | Base():value(20) {}
    method test1 (line 23) | void test1() { cout << "Base test1..." << endl; }
  class Derived (line 33) | class Derived : Base {
    method test2 (line 36) | void test2() { cout << "value is " << value << endl; }
  function main (line 40) | int main()

FILE: english/basic_content/using/using_derived.cpp
  class Base (line 12) | class Base{
    method f (line 14) | void f(){ cout<<"f()"<<endl;
    method f (line 16) | void f(int n){
  class Derived (line 21) | class Derived : private Base {
    method f (line 24) | void f(int n){
  function main (line 29) | int main()

FILE: english/basic_content/using/using_global.cpp
  function func (line 13) | void func()
  type ns1 (line 18) | namespace ns1 {
    function func (line 19) | void func()
  type ns2 (line 25) | namespace ns2 {
    function func (line 31) | void func()
  function main (line 38) | int main()

FILE: english/basic_content/using/using_typedef.cpp
  function main (line 18) | int main()

FILE: english/basic_content/virtual/set1/emp.cpp
  class Employee (line 5) | class Employee
    method raiseSalary (line 8) | virtual void raiseSalary()
    method promote (line 13) | virtual void promote()
  class Manager (line 17) | class Manager: public Employee {
    method raiseSalary (line 18) | virtual void raiseSalary()
    method promote (line 23) | virtual void promote()
  class Engineer (line 26) | class Engineer: public Employee {
    method raiseSalary (line 27) | virtual void raiseSalary()
    method promote (line 32) | virtual void promote()
  function globalRaiseSalary (line 41) | void globalRaiseSalary(Employee *emp[], int n)
  function main (line 48) | int main(){

FILE: english/basic_content/virtual/set2/default_arg.cpp
  class Base (line 13) | class Base
    method fun (line 16) | virtual void fun ( int x = 10 )
  class Derived (line 22) | class Derived : public Base
    method fun (line 25) | virtual void fun ( int x=20 )
  function main (line 32) | int main()

FILE: english/basic_content/virtual/set3/copy_consrtuct.cpp
  class Base (line 4) | class Base
  class Derived (line 10) | class Derived : public Base
    method Derived (line 13) | Derived()
    method Derived (line 18) | Derived(const Derived &rhs)
  function main (line 29) | int main()

FILE: english/basic_content/virtual/set3/full_virde.cpp
  class base (line 17) | class base {
    method base (line 19) | base()
  class derived (line 25) | class derived: public base {
    method derived (line 27) | derived()
  function main (line 33) | int main(void)

FILE: english/basic_content/virtual/set3/inline_virtual.cpp
  class Base (line 3) | class Base
    method who (line 6) | inline virtual void who()
  class Derived (line 12) | class Derived : public Base
    method who (line 15) | inline void who()  // 不写inline时隐式内联
  function main (line 21) | int main()

FILE: english/basic_content/virtual/set3/static_error.cpp
  function fun (line 12) | virtual static void fun()  { }
  function fun (line 13) | static void fun() const { }

FILE: english/basic_content/virtual/set3/vir_con.cpp
  class Base (line 21) | class Base
    method Base (line 24) | Base() { }
  class Derived1 (line 38) | class Derived1 : public Base
    method Derived1 (line 41) | Derived1()
    method Derived1 (line 46) | Derived1(const Derived1& rhs)
    method ChangeAttributes (line 56) | void ChangeAttributes()
    method Base (line 61) | Base *Clone()
  class Derived2 (line 67) | class Derived2 : public Base
    method Derived2 (line 70) | Derived2()
    method Derived2 (line 75) | Derived2(const Derived2& rhs)
    method ChangeAttributes (line 85) | void ChangeAttributes()
    method Base (line 90) | Base *Clone()
  class Derived3 (line 96) | class Derived3 : public Base
    method Derived3 (line 99) | Derived3()
    method Derived3 (line 104) | Derived3(const Derived3& rhs)
    method ChangeAttributes (line 114) | void ChangeAttributes()
    method Base (line 119) | Base *Clone()
  function Base (line 127) | Base *Base::Create(int id)
    method Base (line 24) | Base() { }
  class User (line 148) | class User
    method User (line 151) | User() : pBase(0)
    method Action (line 179) | void Action()
  function main (line 198) | int main()

FILE: english/basic_content/virtual/set3/vir_de.cpp
  class base (line 19) | class base {
    method base (line 21) | base()
  class derived (line 27) | class derived: public base {
    method derived (line 29) | derived()
  function main (line 35) | int main(void)

FILE: english/basic_content/virtual/set3/virtual_function.cpp
  class Derived (line 15) | class Derived
    method fun (line 25) | void fun() { cout << "Derived Fun"; }
  class Base (line 17) | class Base {
    method fun (line 19) | virtual void fun() { cout << "Base Fun"; }
  class Derived (line 23) | class Derived: public Base {
    method fun (line 25) | void fun() { cout << "Derived Fun"; }
  function main (line 28) | int main()

FILE: english/basic_content/virtual/set3/virtual_function1.cpp
  class Derived (line 4) | class Derived
    method fun (line 14) | void fun() { cout << "Derived Fun"; }
  class Base (line 6) | class Base {
    method fun (line 8) | virtual void fun() { cout << "Base Fun"; }
  class Derived (line 12) | class Derived: public Base {
    method fun (line 14) | void fun() { cout << "Derived Fun"; }
  function main (line 17) | int main()

FILE: english/basic_content/virtual/set3/virtual_inline.cpp
  class Base (line 13) | class Base
    method who (line 16) | virtual void who()
  class Derived (line 21) | class Derived: public Base
    method who (line 24) | void who()
  function main (line 30) | int main()

FILE: english/basic_content/virtual/set4/rtti.cpp
  class B (line 14) | class B { virtual void fun() {} }
    method fun (line 14) | virtual void fun() {}
  class D (line 15) | class D: public B { }
  function main (line 17) | int main()

FILE: english/basic_content/virtual/set4/warn_rtti.cpp
  class A (line 5) | class A{
  class B (line 11) | class B{
  class D (line 19) | class D: public A{
  class E (line 25) | class E : private A{
  class F (line 31) | class F : private B{

FILE: english/basic_content/volatile/noopt_vola.cpp
  function main (line 3) | int main(void)

FILE: english/basic_content/volatile/volatile.cpp
  function main (line 4) | int main(void)

FILE: english/basic_content/vptr_vtable/vptr1.cpp
  class Base (line 23) | class Base
    method Base (line 26) | Base(){}
    method fun1 (line 27) | virtual void fun1()
    method fun2 (line 31) | virtual void fun2()
    method fun3 (line 35) | virtual void fun3(){}
  class Derived (line 43) | class Derived: public Base
    method Derived (line 46) | Derived(){}
    method fun1 (line 47) | void fun1()
    method fun2 (line 51) | void fun2()
  function Fun (line 66) | Fun getAddr(void* obj,unsigned int offset)
  function main (line 80) | int main(void)

FILE: learn_class/modern_cpp_30/RAII/RAII.cpp
  type shape_type (line 6) | enum class shape_type {
  class shape (line 12) | class shape {
    method shape (line 14) | shape() { cout << "shape" << endl; }
    method print (line 16) | virtual void print() { cout << "I am shape" << endl; }
  class circle (line 21) | class circle : public shape {
    method circle (line 23) | circle() { cout << "circle" << endl; }
    method print (line 25) | void print() { cout << "I am circle" << endl; }
  class triangle (line 28) | class triangle : public shape {
    method triangle (line 30) | triangle() { cout << "triangle" << endl; }
    method print (line 32) | void print() { cout << "I am triangle" << endl; }
  class rectangle (line 35) | class rectangle : public shape {
    method rectangle (line 37) | rectangle() { cout << "rectangle" << endl; }
    method print (line 39) | void print() { cout << "I am rectangle" << endl; }
  function shape (line 43) | shape *create_shape(shape_type type) {
    method shape (line 14) | shape() { cout << "shape" << endl; }
    method print (line 16) | virtual void print() { cout << "I am shape" << endl; }
  class shape_wrapper (line 54) | class shape_wrapper {
    method shape_wrapper (line 56) | explicit shape_wrapper(shape *ptr = nullptr) : ptr_(ptr) {}
    method shape (line 60) | shape *get() const { return ptr_; }
  function foo (line 66) | void foo() {
  function main (line 71) | int main() {

FILE: learn_class/modern_cpp_30/RAII/heap.cpp
  class bar (line 5) | class bar {}
  function foo (line 8) | void foo() {
  function bar (line 14) | bar *make_bar() {
  function foo1 (line 25) | void foo1() {
  function main (line 31) | int main() {

FILE: learn_class/modern_cpp_30/RAII/stack.cpp
  class Obj (line 5) | class Obj {
    method Obj (line 7) | Obj() { puts("Obj()"); }
  function foo (line 10) | void foo(int n) {
  function main (line 16) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/SFINAE.cpp
  class IsClassT (line 8) | class IsClassT {
  type A (line 25) | struct A {}
  function main (line 27) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/auto.cpp
  function g (line 14) | decltype(t.serialize()) g(const T &t) {}
  function g (line 20) | auto g(const T &t) -> decltype(t.serialize()) {}
  function myFunction (line 23) | auto myFunction() // Automagically figures out that myFunction returns i...

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/blending1.cpp
  type hasSerialize (line 10) | struct hasSerialize {
    method test (line 15) | static constexpr decltype(std::declval<C>().serialize(), bool()) test(...
    method test (line 21) | static constexpr bool test(...) {
  function serialize (line 30) | std::string serialize(const T &obj) {
  function main (line 38) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/blending2.cpp
  type hasSerialize (line 10) | struct hasSerialize : std::false_type {
  type hasSerialize<T, decltype(std::declval<T>().serialize())> (line 14) | struct hasSerialize<T, decltype(std::declval<T>().serialize())> : std::t...
  function serialize (line 19) | std::string serialize(const T &obj) {
  function main (line 27) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/combiningAndGenius.cpp
  type hasSerialize (line 10) | struct hasSerialize {
    type reallyHas (line 21) | struct reallyHas
    method yes (line 25) | static yes &test(reallyHas<std::string (C::*)(), &C::serialize> * /*un...
    method yes (line 29) | static yes &test(reallyHas<std::string (C::*)() const, &C::serialize> ...
    method no (line 35) | static no &test(...) { /* dark matter */ }
  type D (line 43) | struct D : A {
    method serialize (line 44) | std::string serialize() const {
  function testHasSerialize (line 50) | bool testHasSerialize(const T & /*t*/) { return hasSerialize<T>::value; }
  type E (line 53) | struct E {
    type Functor (line 54) | struct Functor {
  function serialize (line 64) | std::string serialize(const T &obj) {
  function main (line 72) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/constexpr.cpp
  function factorial (line 6) | constexpr int factorial(int n) {
  type testStruct (line 10) | struct testStruct : std::true_type {
  function main (line 13) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/decltype.cpp
  type Default (line 5) | struct Default {
    method foo (line 6) | int foo() const {return 1;}
  type NonDefault (line 9) | struct NonDefault {
    method NonDefault (line 10) | NonDefault(const NonDefault&) {}
    method foo (line 11) | int foo() const {return 1;}
  function main (line 14) | int main()

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/fis_valid.cpp
  type container (line 10) | struct container {
    method testValidity (line 17) | constexpr auto testValidity(int /* unused */)
    method testValidity (line 24) | constexpr std::false_type testValidity(...) {
  function is_valid (line 42) | constexpr auto is_valid(const UnnamedType &t) {
  function serialize (line 52) | auto serialize(T &obj)
  function serialize (line 58) | auto serialize(T &obj)
  function main (line 63) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/hana.cpp
  function main (line 12) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/is_valid.cpp
  type container (line 9) | struct container {
  function is_valid (line 41) | constexpr auto is_valid(const UnnamedType &t) {
  function serialize (line 51) | auto serialize(T &obj)
  function serialize (line 57) | auto serialize(T &obj)
  function main (line 62) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/lambda.cpp
  type l5UnamedType (line 7) | struct l5UnamedType {
  function fun (line 16) | void fun(A a,B b,C c) {
  function main (line 49) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/overload1.cpp
  function main (line 12) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/overload2.cpp
  function f (line 6) | std::string f(...) // Variadic functions are so "untyped" that...
  function f (line 12) | std::string f(const T &t)// ...this templated function got the precedence!
  function main (line 18) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/p1SFINAE.cpp
  function f (line 16) | void f(const T &t, typename T::iterator *it = nullptr) {}
  function f (line 19) | void f(...) {}
  function main (line 21) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/p2SFINAE.cpp
  function f (line 8) | void f(T t) { t.hahahaICrash(); }
  function f (line 9) | void f(...) { }
  function main (line 11) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/packis_valid.cpp
  type container (line 8) | struct container
  function is_valid (line 39) | constexpr auto is_valid(UnnamedType&& t)
  function serialize (line 50) | auto serialize(T &obj)
  function serialize (line 56) | auto serialize(T &obj)
  function main (line 61) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/serialize.cpp
  function serialize (line 17) | std::string serialize(T const &obj) {
  function main (line 26) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/sizeof1.cpp
  function type_test (line 9) | type_test &f() {}
  function main (line 11) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/sizeof2.cpp
  function yes (line 11) | yes &f1() {}
  function no (line 12) | no &f2() {}
  function main (line 14) | int main() {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/structData.h
  type A (line 8) | struct A {
  type C (line 23) | struct C {

FILE: learn_class/modern_cpp_30/SFINAE/sfinae paper/timeGenius.cpp
  type hasSerialize (line 10) | struct hasSerialize {
    type reallyHas (line 21) | struct reallyHas
    method yes (line 25) | static yes &test(reallyHas<std::string (C::*)(), &C::serialize> * /*un...
    method yes (line 29) | static yes &test(reallyHas<std::string (C::*)() const, &C::serialize> ...
    method no (line 35) | static no &test(...) { /* dark matter */ }
  type enable_if (line 44) | struct enable_if {
  type enable_if<true, T> (line 48) | struct enable_if<true, T> {
  function serialize (line 53) | typename enable_if<hasSerialize<T>::value, std::string>::type serialize(...
  function serialize (line 58) | typename enable_if<!hasSerialize<T>::value, std::string>::type serialize...
  function main (line 62) | int main() {

FILE: learn_class/modern_cpp_30/compilercompute/IF.cpp
  type IF (line 11) | struct IF
  type IF<true, Then, Else> (line 13) | struct IF<true, Then, Else> {
  type IF<false, Then, Else> (line 17) | struct IF<false, Then, Else> {
  type isEven (line 22) | struct isEven {
  type Add_ (line 26) | struct Add_ {
  type Sub_ (line 30) | struct Sub_ {
  type addSub (line 35) | struct addSub {
  function main (line 40) | int main() {

FILE: learn_class/modern_cpp_30/compilercompute/WhileLoop.cpp
  type WhileLoop (line 11) | struct WhileLoop
  type WhileLoop<true, Body> (line 13) | struct WhileLoop<true, Body> {
  type WhileLoop<false, Body> (line 18) | struct WhileLoop<false, Body> {
  type While (line 22) | struct While {
  type my (line 27) | namespace my {
    type integral_constant (line 28) | struct integral_constant {
  type SumLoop (line 34) | struct SumLoop {
  type Sum (line 49) | struct Sum { typedef SumLoop<0, n> type; }
  function main (line 53) | int main() {

FILE: learn_class/modern_cpp_30/compilercompute/factorial.cpp
  type factorial (line 9) | struct factorial {
  type factorial<0> (line 14) | struct factorial<0> { static const int value = 1; }
  function main (line 16) | int main() {

FILE: learn_class/modern_cpp_30/compilercompute/fmap.cpp
  function fmap (line 12) | auto fmap(F &&f, R &&inputs) {
  function add_1 (line 24) | int add_1(int x) { return x + 1; }
  function main (line 26) | int main() {

FILE: learn_class/modern_cpp_30/compilerpoly/template.cpp
  function isEqual (line 13) | bool isEqual(T t1, T t2) {
  function isEqual (line 20) | bool isEqual(const char *t1, const char *t2) {
  function isEqual (line 34) | bool isEqual(T a, double b) {
  class comp (line 43) | class comp {
    method isEqual (line 45) | bool isEqual(T t1, T t2) {
  class comp<const char *> (line 53) | class comp<const char *> {
    method isEqual (line 55) | bool isEqual(const char *t1, const char *t2) {
  class comp<T *> (line 63) | class comp<T *> {
    method isEqual (line 65) | bool isEqual(T *t1, T *t2) {
  function main (line 71) | int main() {

FILE: learn_class/modern_cpp_30/constexpr/container.cpp
  function main (line 13) | int main() {

FILE: learn_class/modern_cpp_30/constexpr/newconstexpr.cpp
  type magic (line 12) | struct magic {
  type my (line 26) | namespace my {
  class A (line 32) | class A {}
  class B (line 35) | class B {
  function main (line 39) | int main() {

FILE: learn_class/modern_cpp_30/constexpr/output_container.h
  type CHARS (line 32) | enum CHARS {

FILE: learn_class/modern_cpp_30/constexpr/sqrt.cpp
  function sqr (line 8) | int sqr(int n) { return n * n; }
  function rand (line 10) | int rand() { return std::rand(); }
  function sqr1 (line 13) | constexpr int sqr1(int n) { return n * n; }
  function factorial (line 15) | constexpr int factorial(int n) {
  function main (line 30) | int main() {

FILE: learn_class/modern_cpp_30/constexpr/test3.cpp
  class test3 (line 7) | class test3 {
    method getvalue (line 13) | constexpr int getvalue() const { return (value); }
    method test3 (line 15) | constexpr test3(int Value) : value(Value) {}
  function main (line 18) | int main() {

FILE: learn_class/modern_cpp_30/container1/container.cpp
  function main (line 12) | int main() {

FILE: learn_class/modern_cpp_30/container1/vector_l.cpp
  class Obj1 (line 9) | class Obj1 {
    method Obj1 (line 11) | Obj1() { cout << "Obj1()\n"; }
    method Obj1 (line 12) | Obj1(const Obj1 &) { cout << "Obj1(const Obj1&)\n"; }
    method Obj1 (line 13) | Obj1(Obj1 &&) { cout << "Obj1(Obj1&&)\n"; }
  class Obj2 (line 16) | class Obj2 {
    method Obj2 (line 18) | Obj2() { cout << "Obj2()\n"; }
    method Obj2 (line 19) | Obj2(const Obj2 &) { cout << "Obj2(const Obj2&)\n"; }
    method Obj2 (line 20) | Obj2(Obj2 &&) noexcept { cout << "Obj2(Obj2&&)\n"; }
  function main (line 23) | int main() {

FILE: learn_class/modern_cpp_30/container2/array.cpp
  function test (line 12) | void test(int a[8]) { cout << ARRAY_LEN(a) << endl; }
  function test1 (line 14) | void test1(int arr[]) {
  function main (line 23) | int main() {

FILE: learn_class/modern_cpp_30/container2/hash.cpp
  function main (line 14) | int main() {

FILE: learn_class/modern_cpp_30/container2/priority_queue.cpp
  function main (line 14) | int main() {

FILE: learn_class/modern_cpp_30/container2/relacontainer.cpp
  function main (line 15) | int main() {

FILE: learn_class/modern_cpp_30/container2/unorder.cpp
  type std (line 13) | namespace std {
    type hash<complex<T>> (line 15) | struct hash<complex<T>> {
  function main (line 24) | int main() {

FILE: learn_class/modern_cpp_30/exception/exception.cpp
  function main (line 17) | int main()

FILE: learn_class/modern_cpp_30/functionLambda/adder.cpp
  type adder (line 8) | struct adder {
    method adder (line 9) | adder(int n) : n_(n) {}
  function main (line 17) | int main() {

FILE: learn_class/modern_cpp_30/functionLambda/autoLambda.cpp
  function get_count (line 12) | int get_count() {
  class task (line 17) | class task {
    method task (line 19) | task(int data) : data_(data) {}
    method lazy_launch (line 32) | auto lazy_launch() {
    method calculate (line 42) | void calculate() {
  function main (line 52) | int main() {

FILE: learn_class/modern_cpp_30/functionLambda/function.cpp
  function main (line 11) | int main() {

FILE: learn_class/modern_cpp_30/literalAssert/assert.cpp
  function main (line 8) | int main() {

FILE: learn_class/modern_cpp_30/literalAssert/default_delete.cpp
  class myFun (line 5) | class myFun {
    method myFun (line 7) | myFun() = default;
    method myFun (line 9) | myFun(const myFun &) = default;
    method myFun (line 11) | myFun &operator=(const myFun &) = default;
    method myFun (line 13) | myFun(myFun &&) = delete;
    method myFun (line 15) | myFun &operator=(myFun &&) = delete;

FILE: learn_class/modern_cpp_30/literalAssert/literal.cpp
  type length (line 17) | struct length {
    type unit (line 19) | enum unit {
    method length (line 32) | explicit length(double v, unit u = metre) { value = v * factors[u]; }
  function length (line 35) | length operator+(length lhs, length rhs) {
    type unit (line 19) | enum unit {
    method length (line 32) | explicit length(double v, unit u = metre) { value = v * factors[u]; }
  function length (line 39) | length operator"" _m(long double v) { return length(v, length::metre); }
    type unit (line 19) | enum unit {
    method length (line 32) | explicit length(double v, unit u = metre) { value = v * factors[u]; }
  function length (line 41) | length operator"" _cm(long double v) { return length(v, length::centimet...
    type unit (line 19) | enum unit {
    method length (line 32) | explicit length(double v, unit u = metre) { value = v * factors[u]; }
  function main (line 44) | int main() {

FILE: learn_class/modern_cpp_30/literalAssert/overridefinal.cpp
  class A (line 5) | class A {
  class B (line 12) | class B : public A {
  class C (line 20) | class C final : public B {
  class D (line 27) | class D : public C {

FILE: learn_class/modern_cpp_30/memorymodel_atomic/barrier_singleton.cpp
  class singleton (line 24) | class singleton {
    method singleton (line 26) | singleton() {}
  function singleton (line 36) | singleton *singleton::instance() {
    method singleton (line 26) | singleton() {}

FILE: learn_class/modern_cpp_30/memorymodel_atomic/cpulpuls11_singleton.cpp
  class singleton (line 13) | class singleton {
    method singleton (line 15) | singleton() {}
  function singleton (line 31) | singleton *singleton::instance() {
    method singleton (line 15) | singleton() {}

FILE: learn_class/modern_cpp_30/memorymodel_atomic/dcl_singleton.cpp
  class singleton (line 10) | class singleton {
    method singleton (line 12) | singleton() {}
    class CGarbo (line 20) | class CGarbo
  function singleton (line 35) | singleton* singleton::instance() {
    method singleton (line 12) | singleton() {}
    class CGarbo (line 20) | class CGarbo

FILE: learn_class/modern_cpp_30/memorymodel_atomic/hungrysingleton.cpp
  class singleton (line 5) | class singleton {
    method singleton (line 7) | singleton() {}
  function singleton (line 14) | singleton* singleton::instance() {
    method singleton (line 7) | singleton() {}

FILE: learn_class/modern_cpp_30/memorymodel_atomic/iazysingleton.cpp
  class singleton (line 5) | class singleton {
    method singleton (line 7) | singleton() {}
  function singleton (line 15) | singleton* singleton::instance() {
    method singleton (line 7) | singleton() {}

FILE: learn_class/modern_cpp_30/memorymodel_atomic/lock_singleton.cpp
  class singleton (line 9) | class singleton {
    method singleton (line 11) | singleton() {}
  function singleton (line 20) | singleton* singleton::instance() {
    method singleton (line 11) | singleton() {}

FILE: learn_class/modern_cpp_30/memorymodel_atomic/pthreadoncesingleton.cpp
  class singleton (line 8) | class singleton {
    method init (line 14) | static void init() {
    method singleton (line 21) | singleton *instance() {

FILE: learn_class/modern_cpp_30/memorymodel_atomic/static_local_singleton.cpp
  class singleton (line 9) | class singleton {
    method singleton (line 12) | singleton() {}
  function singleton (line 17) | singleton *singleton::instance() {
    method singleton (line 12) | singleton() {}

FILE: learn_class/modern_cpp_30/obj/all.cpp
  type Test (line 9) | struct Test {
    method Test (line 10) | Test() {
    method Test (line 14) | Test(const Test &) {
    method Test (line 18) | Test &operator=(const Test &t) {
    method Test (line 23) | Test(Test &&t) { std::cout << "move construct a Test object" << std::e...
    method Test (line 25) | Test &operator=(Test &&t) {
  function Test (line 35) | Test getTest() {
    method Test (line 10) | Test() {
    method Test (line 14) | Test(const Test &) {
    method Test (line 18) | Test &operator=(const Test &t) {
    method Test (line 23) | Test(Test &&t) { std::cout << "move construct a Test object" << std::e...
    method Test (line 25) | Test &operator=(Test &&t) {
  function Test (line 40) | Test getTestWithName() {
    method Test (line 10) | Test() {
    method Test (line 14) | Test(const Test &) {
    method Test (line 18) | Test &operator=(const Test &t) {
    method Test (line 23) | Test(Test &&t) { std::cout << "move construct a Test object" << std::e...
    method Test (line 25) | Test &operator=(Test &&t) {
  function main (line 52) | int main() {

FILE: learn_class/modern_cpp_30/obj/obj1.cpp
  class A (line 12) | class A {
    method A (line 14) | A() { cout << "Create A\n"; }
    method A (line 18) | A(const A &) { cout << "Copy A\n"; }
    method A (line 20) | A(A &&) { cout << "Move A\n"; }
    method A (line 22) | A &operator=(const A &a) {
    method A (line 27) | A &operator=(A &&a) {
  function A (line 34) | A getA_unnamed() { return A(); }
    method A (line 14) | A() { cout << "Create A\n"; }
    method A (line 18) | A(const A &) { cout << "Copy A\n"; }
    method A (line 20) | A(A &&) { cout << "Move A\n"; }
    method A (line 22) | A &operator=(const A &a) {
    method A (line 27) | A &operator=(A &&a) {
  function main (line 36) | int main() {

FILE: learn_class/modern_cpp_30/obj/obj2.cpp
  class A (line 12) | class A {
    method A (line 14) | A() { cout << "Create A\n"; }
    method A (line 18) | A(const A &) { cout << "Copy A\n"; }
    method A (line 20) | A(A &&) { cout << "Move A\n"; }
    method A (line 22) | A &operator=(const A &a) {
    method A (line 27) | A &operator=(A &&a) {
  function A (line 34) | A getA_named() {
    method A (line 14) | A() { cout << "Create A\n"; }
    method A (line 18) | A(const A &) { cout << "Copy A\n"; }
    method A (line 20) | A(A &&) { cout << "Move A\n"; }
    method A (line 22) | A &operator=(const A &a) {
    method A (line 27) | A &operator=(A &&a) {
  function main (line 39) | int main() {

FILE: learn_class/modern_cpp_30/obj/obj3.cpp
  class A (line 10) | class A {
    method A (line 12) | A() { cout << "Create A\n"; }
    method A (line 16) | A(const A &) { cout << "Copy A\n"; }
    method A (line 18) | A(A &&) { cout << "Move A\n"; }
    method A (line 20) | A &operator=(const A &a) {
    method A (line 25) | A &operator=(A &&a) {
  function A (line 31) | A getA_duang() {
    method A (line 12) | A() { cout << "Create A\n"; }
    method A (line 16) | A(const A &) { cout << "Copy A\n"; }
    method A (line 18) | A(A &&) { cout << "Move A\n"; }
    method A (line 20) | A &operator=(const A &a) {
    method A (line 25) | A &operator=(A &&a) {
  function main (line 41) | int main() {

FILE: learn_class/modern_cpp_30/obj/obj4.cpp
  class A (line 10) | class A {
    method A (line 12) | A() { cout << "Create A\n"; }
    method A (line 16) | A(const A &) { cout << "Copy A\n"; }
    method A (line 18) | A(A &&) = delete;
  function A (line 21) | A getA_duang() {
    method A (line 12) | A() { cout << "Create A\n"; }
    method A (line 16) | A(const A &) { cout << "Copy A\n"; }
    method A (line 18) | A(A &&) = delete;
  function main (line 31) | int main() { auto a = getA_duang(); }

FILE: learn_class/modern_cpp_30/obj/obj5.cpp
  class A (line 10) | class A {
    method A (line 12) | A() { cout << "Create A\n"; }
    method A (line 20) | A(const A &&) = delete;
    method A (line 21) | A(A &&) = delete;
  function A (line 24) | A getA_unnamed() { return A(); }
    method A (line 12) | A() { cout << "Create A\n"; }
    method A (line 20) | A(const A &&) = delete;
    method A (line 21) | A(A &&) = delete;
  function main (line 26) | int main() { auto a = getA_unnamed(); }

FILE: learn_class/modern_cpp_30/reference/collapses.cpp
  function f (line 9) | void f(T &&param) {
  class Widget (line 15) | class Widget {
    method judge (line 19) | void judge() {
    method f (line 24) | void f(LvalueRefType&& param) {
  function main (line 30) | int main() {

FILE: learn_class/modern_cpp_30/reference/forward.cpp
  function overloaded (line 7) | void overloaded( int const &arg ) { std::cout << "by lvalue\n"; }
  function overloaded (line 8) | void overloaded( int && arg ) { std::cout << "by rvalue\n"; }
  function forwarding (line 13) | void forwarding( t && arg ) {
  function foo (line 21) | void foo(const shape&)
  function foo (line 25) | void foo(shape&&)
  function bar (line 30) | void bar(T&& s)
  function main (line 34) | int main() {

FILE: learn_class/modern_cpp_30/reference/lifetime.cpp
  class result (line 10) | class result {
    method result (line 12) | result() { puts("result()"); }
  function result (line 17) | result process_shape(const shape &shape1, const shape &shape2) {
    method result (line 12) | result() { puts("result()"); }
  class Base (line 23) | class Base {
    method Base (line 25) | Base() {
  class Derived (line 34) | class Derived : public Base {
    method Derived (line 36) | Derived() {
  function string (line 45) | string f() { return "abc"; }
  function g (line 47) | void g() {
  function Derived (line 52) | Derived factory() {
    method Derived (line 36) | Derived() {
  function main (line 56) | int main() {

FILE: learn_class/modern_cpp_30/reference/ref.cpp
  class Obj (line 8) | class Obj {
    method Obj (line 10) | Obj()
    method Obj (line 14) | Obj(const Obj&)
    method Obj (line 19) | Obj(Obj&&)
  function Obj (line 24) | Obj simple()
    method Obj (line 10) | Obj()
    method Obj (line 14) | Obj(const Obj&)
    method Obj (line 19) | Obj(Obj&&)
  function Obj (line 30) | Obj simple_with_move()
    method Obj (line 10) | Obj()
    method Obj (line 14) | Obj(const Obj&)
    method Obj (line 19) | Obj(Obj&&)
  function Obj (line 36) | Obj complicated(int n)
    method Obj (line 10) | Obj()
    method Obj (line 14) | Obj(const Obj&)
    method Obj (line 19) | Obj(Obj&&)
  function main (line 47) | int main()

FILE: learn_class/modern_cpp_30/reference/reference.cpp
  type As (line 15) | struct As
  function As (line 20) | As&& ff(){
  function main (line 24) | int main() {

FILE: learn_class/modern_cpp_30/reference/shape.h
  function class (line 5) | class shape {
  function class (line 14) | class circle : public shape {
  function class (line 24) | class triangle : public shape {
  function class (line 34) | class rectangle : public shape {

FILE: learn_class/modern_cpp_30/smart_ptr/auto_scope.cpp
  class auto_ptr (line 5) | class auto_ptr {
    method auto_ptr (line 7) | explicit auto_ptr(T *ptr = nullptr) noexcept : ptr_(ptr) {}
    method T (line 11) | T &operator*() const noexcept { return *ptr_; }
    method T (line 13) | T *operator->() const noexcept { return ptr_; }
    method T (line 17) | T *get() const noexcept { return ptr_; }
    method auto_ptr (line 21) | auto_ptr(auto_ptr &other) noexcept { ptr_ = other.release(); }
    method auto_ptr (line 24) | auto_ptr &operator=(auto_ptr &rhs) noexcept {
    method T (line 33) | T *release() noexcept {
    method swap (line 39) | void swap(auto_ptr &rhs) noexcept {
  function swap (line 48) | void swap(auto_ptr<T> &lhs, auto_ptr<T> &rhs) noexcept {
  class scoped_ptr (line 53) | class scoped_ptr // noncopyable
    method scoped_ptr (line 57) | explicit scoped_ptr(T *ptr = 0) noexcept : ptr_(ptr) {}
    method reset (line 61) | void reset(T *p = 0) noexcept { scoped_ptr(p).swap(*this); }
    method T (line 63) | T &operator*() const noexcept { return *ptr_; }
    method T (line 65) | T *operator->() const noexcept { return ptr_; }
    method T (line 67) | T *get() const noexcept { return ptr_; }
    method swap (line 69) | void swap(scoped_ptr &rhs) noexcept {
  function swap (line 82) | void swap(scoped_ptr<T> &lhs, scoped_ptr<T> &rhs) noexcept {
  function main (line 86) | int main() {

FILE: learn_class/modern_cpp_30/smart_ptr/shared_ptr.cpp
  class shared_count (line 6) | class shared_count {
    method shared_count (line 8) | shared_count() : count_(1) {}
    method add_count (line 11) | void add_count() { ++count_; }
    method reduce_count (line 14) | long reduce_count() { return --count_; }
    method get_count (line 17) | long get_count() const { return count_; }
  class shared_ptr (line 23) | class shared_ptr {
    method shared_ptr (line 25) | explicit shared_ptr(T *ptr = nullptr) noexcept : ptr_(ptr) {
    method shared_ptr (line 33) | shared_ptr(const shared_ptr<U> &other, T *ptr) noexcept {
    method T (line 50) | T &operator*() const noexcept { return *ptr_; }
    method T (line 52) | T *operator->() const noexcept { return ptr_; }
    method T (line 56) | T *get() const noexcept { return ptr_; }
    method shared_ptr (line 62) | shared_ptr(const shared_ptr<U> &other) noexcept {
    method shared_ptr (line 71) | shared_ptr(shared_ptr<U> &&other) noexcept {
    method shared_ptr (line 82) | shared_ptr &operator=(shared_ptr rhs) noexcept {
    method swap (line 87) | void swap(shared_ptr &rhs) noexcept {
    method use_count (line 93) | long use_count() const noexcept {
  function swap (line 107) | void swap(shared_ptr<T> &lhs, shared_ptr<T> &rhs) noexcept {
  function dynamic_pointer_cast (line 112) | shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U> &other) noexcept {
  function static_pointer_cast (line 118) | shared_ptr<T> static_pointer_cast(const shared_ptr<U> &other) noexcept {
  function const_pointer_cast (line 124) | shared_ptr<T> const_pointer_cast(const shared_ptr<U> &other) noexcept {
  function reinterpret_pointer_cast (line 130) | shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U> &other) noexc...
  function main (line 135) | int main() {

FILE: learn_class/modern_cpp_30/smart_ptr/unique_ptr.cpp
  class unique_ptr (line 7) | class unique_ptr {
    method unique_ptr (line 9) | explicit unique_ptr(T *ptr = nullptr) noexcept : ptr_(ptr) {}
    method T (line 13) | T &operator*() const noexcept { return *ptr_; }
    method T (line 15) | T *operator->() const noexcept { return ptr_; }
    method T (line 19) | T *get() const noexcept { return ptr_; }
    method unique_ptr (line 21) | unique_ptr(unique_ptr &&other) noexcept {
    method unique_ptr (line 26) | unique_ptr(unique_ptr<U> &&other) noexcept {
    method unique_ptr (line 32) | unique_ptr &operator=(unique_ptr rhs) noexcept {
    method T (line 38) | T *release() noexcept {
    method swap (line 44) | void swap(unique_ptr &rhs) noexcept {
  function swap (line 53) | void swap(unique_ptr<T> &lhs, unique_ptr<T> &rhs) {
  function main (line 57) | int main() {

FILE: learn_class/modern_cpp_30/smart_ptr/unique_ptr_U.cpp
  class unique_ptr (line 7) | class unique_ptr {
    method unique_ptr (line 9) | explicit unique_ptr(T *ptr = nullptr) noexcept : ptr_(ptr) {}
    method T (line 13) | T &operator*() const noexcept { return *ptr_; }
    method T (line 15) | T *operator->() const noexcept { return ptr_; }
    method T (line 19) | T *get() const noexcept { return ptr_; }
    method unique_ptr (line 21) | unique_ptr(unique_ptr<U> &&other) noexcept {
    method unique_ptr (line 27) | unique_ptr &operator=(unique_ptr rhs) noexcept {
    method T (line 33) | T *release() noexcept {
    method swap (line 39) | void swap(unique_ptr &rhs) noexcept {
  function main (line 48) | int main() {

FILE: practical_exercises/10_day_practice/day1/print.cpp
  function main (line 4) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day1/runnian.cpp
  function main (line 4) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day1/union.cpp
  function main (line 13) | int main() {

FILE: practical_exercises/10_day_practice/day10/file/10-4.cpp
  function main (line 4) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day10/file/12-1.cpp
  function main (line 4) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day10/file/12-2.cpp
  function main (line 3) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day10/file/12-3.cpp
  function main (line 6) | int main() {

FILE: practical_exercises/10_day_practice/day10/file/12-5.cpp
  function main (line 5) | int main() {

FILE: practical_exercises/10_day_practice/day10/file/12-6.cpp
  function main (line 5) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day10/file/12-7.cpp
  function main (line 5) | int main() {

FILE: practical_exercises/10_day_practice/day10/file/12-9.cpp
  class Employee (line 6) | class Employee {
    method Employee (line 13) | Employee() {}
    method Employee (line 14) | Employee(int num, char *Name, int Age, double Salary) {
    method display (line 20) | void display() {
  function main (line 25) | int main() {

FILE: practical_exercises/10_day_practice/day10/file/input/get.cpp
  function main (line 4) | int main() {

FILE: practical_exercises/10_day_practice/day10/file/input/get2.cpp
  function main (line 6) | int main() {

FILE: practical_exercises/10_day_practice/day10/file/input/getline.cpp
  function main (line 8) | int main() {

FILE: practical_exercises/10_day_practice/day10/file/practice.cpp
  class Person (line 7) | class Person {
    method Person (line 15) | Person() {}
    method Person (line 16) | Person(char *n, char *pid, int Age, char *Addr) {
    method display (line 22) | void display() {
  function main (line 26) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day2/compute.cpp
  function main (line 5) | int main(int argc, char const *argv[]) {
  function arctan (line 13) | double arctan(double x) {

FILE: practical_exercises/10_day_practice/day2/enum.cpp
  type weekday (line 5) | enum weekday { s, m, t, w, thu, f, s1 }
  function main (line 7) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day2/hanoi.cpp
  function main (line 6) | int main(int argc, char const *argv[]) {
  function move (line 15) | void move(char A, char B) { cout << A << "->" << B << endl; }
  function hanoi (line 17) | void hanoi(int n, char A, char B, char C) {

FILE: practical_exercises/10_day_practice/day2/pow.cpp
  function main (line 6) | int main(int argc, char const *argv[]) {
  function power (line 23) | double power(double x, int n) {

FILE: practical_exercises/10_day_practice/day2/rec1.cpp
  function main (line 6) | int main(int argc, char const *argv[]) {
  function f (line 15) | int f(int n) {

FILE: practical_exercises/10_day_practice/day2/rec2.cpp
  function main (line 5) | int main(int argc, char const *argv[]) {
  function f (line 15) | int f(int n, int k) {

FILE: practical_exercises/10_day_practice/day2/shaizi.cpp
  function main (line 6) | int main(int argc, char const *argv[]) {
  function rolldice (line 47) | int rolldice() {

FILE: practical_exercises/10_day_practice/day2/st.cpp
  type student (line 4) | struct student {
  function main (line 10) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day2/static.cpp
  function main (line 5) | int main(void) {
  function other (line 24) | void other(void) {

FILE: practical_exercises/10_day_practice/day3/inline.cpp
  function main (line 6) | int main(int argc, char const *argv[]) {
  function CalArea (line 15) | inline double CalArea(double radius) { return 3.14 * radius * radius; }

FILE: practical_exercises/10_day_practice/day3/pratice.cpp
  class Circle (line 15) | class Circle {
  function main (line 32) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day3/predeclare.cpp
  class Fred (line 10) | class Fred
  class Barney (line 11) | class Barney {
    method method (line 23) | void method() {
  class Fred (line 14) | class Fred {
  class Fred (line 19) | class Fred
  class Barney (line 21) | class Barney {
    method method (line 23) | void method() {
  class Fred (line 31) | class Fred {

FILE: practical_exercises/10_day_practice/day3/static_data.cpp
  class Point (line 11) | class Point {
    method Point (line 13) | Point(int xx = 0, int yy = 0) {
    method GetX (line 19) | int GetX() { return X; }
    method GetY (line 20) | int GetY() { return Y; }
    method GetC (line 21) | void GetC() { cout << " Object id=" << countP << endl; }
  function main (line 35) | int main() {

FILE: practical_exercises/10_day_practice/day3/static_member1.cpp
  class Application (line 10) | class Application {
  function main (line 22) | int main() {

FILE: practical_exercises/10_day_practice/day3/static_member2.cpp
  class A (line 4) | class A {
  function main (line 18) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day3/swap.cpp
  function main (line 5) | int main(int argc, char const *argv[]) {
  function swap (line 14) | void swap(int &a, int &b) {

FILE: practical_exercises/10_day_practice/day4/clock/operator.cpp
  class Time (line 4) | class Time {
    method Time (line 9) | Time(int h = 0, int m = 0, int s = 0) : hh(h), mm(m), ss(s) {}
    method ShowTime (line 15) | void ShowTime() { cout << hh << ":" << mm << ":" << ss << endl; }
  function main (line 17) | int main() {

FILE: practical_exercises/10_day_practice/day4/clock/operator_plus.cpp
  class Time (line 7) | class Time {
    method Time (line 9) | Time(int h = 0, int m = 0, int s = 0) {
    method showTime (line 16) | void showTime() {
  function Time (line 23) | Time Time::operator++(int n) {
    method Time (line 9) | Time(int h = 0, int m = 0, int s = 0) {
    method showTime (line 16) | void showTime() {
  function Time (line 28) | Time Time::operator++() {
    method Time (line 9) | Time(int h = 0, int m = 0, int s = 0) {
    method showTime (line 16) | void showTime() {
  function main (line 44) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day4/const/obj_func.cpp
  class R (line 3) | class R {
    method R (line 5) | R(int r1, int r2) {
  function main (line 32) | int main() {

FILE: practical_exercises/10_day_practice/day4/const/obj_ref.cpp
  class A (line 6) | class A {
    method A (line 8) | A(int i, int j) {
  function main (line 16) | int main() {
  function display (line 23) | void display(const double &r)

FILE: practical_exercises/10_day_practice/day4/copy_ctor/clock.cpp
  function main (line 27) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day4/copy_ctor/clock.h
  function class (line 3) | class Clock {

FILE: practical_exercises/10_day_practice/day4/friend/class.cpp
  class A (line 12) | class A {
    method Display (line 16) | void Display() { cout << x << endl; }
  class B (line 21) | class B {
  function main (line 32) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day4/friend/func.cpp
  class Point (line 5) | class Point {
    method Point (line 7) | Point(int x = 0, int y = 0) : X(x), Y(y) {}
    method GetX (line 8) | int GetX() { return X; }
    method GetY (line 9) | int GetY() { return Y; }
  function Distance (line 16) | float Distance(Point &a, Point &b) {
  function main (line 22) | int main() {

FILE: practical_exercises/10_day_practice/day5/ctor_dtor/cseq.cpp
  class A (line 9) | class A {
    method A (line 11) | A() { cout << "Constructing A" << endl; }
  class B (line 14) | class B {
    method B (line 16) | B() { cout << "Constructing B" << endl; }
  class C (line 20) | class C {
    method C (line 22) | C() { cout << "Constructing C" << endl; }
  function main (line 28) | int main() {

FILE: practical_exercises/10_day_practice/day5/ctor_dtor/ctor.cpp
  class Base (line 3) | class Base {
    method Base (line 8) | Base(int a) {
  class Derived (line 14) | class Derived : public Base {
    method Derived (line 19) | Derived(int a, int b) : Base(a) { //派生类构造函数的初始化列表
  function main (line 25) | int main() {

FILE: practical_exercises/10_day_practice/day5/ctor_dtor/ctor_d.cpp
  class A (line 3) | class A {
    method A (line 5) | A() { cout << "Constructing A" << endl; }
  class B (line 8) | class B {
    method B (line 10) | B() { cout << "Constructing B" << endl; }
  class C (line 13) | class C {
    method C (line 15) | C() { cout << "Constructing C" << endl; }
  class D (line 18) | class D : public C {
    method D (line 20) | D() { cout << "Constructing D" << endl; }
  function main (line 27) | int main() {

FILE: practical_exercises/10_day_practice/day5/ctor_dtor/noctor.cpp
  class A (line 3) | class A {
    method A (line 5) | A() { cout << "Constructing A" << endl; }
  class B (line 8) | class B : public A {
  function main (line 12) | int main() {

FILE: practical_exercises/10_day_practice/day5/ctor_dtor/param.cpp
  class Point (line 3) | class Point {
    method Point (line 8) | Point(int a, int b = 0) {
  class Line (line 14) | class Line : public Point {
    method Line (line 19) | Line(int a, int b, int l) : Point(a, b) { //构造函数初始化列表
  function main (line 24) | int main() {

FILE: practical_exercises/10_day_practice/day5/ctor_dtor/seq.cpp
  class A (line 4) | class A {
    method A (line 8) | A(int i = 0) {
  class B (line 13) | class B {
    method B (line 17) | B(int i) {
  class C (line 22) | class C {
    method C (line 26) | C(int i) {
  class D (line 31) | class D : public B {
    method D (line 36) | D() : a4(4), c2(2), c1(1), B(1) { cout << "D-----5" << endl; }
  function main (line 38) | int main() {

FILE: practical_exercises/10_day_practice/day5/inherit_access/private.cpp
  class base (line 3) | class base {
    method setx (line 7) | void setx(int n) { x = n; }
    method getx (line 8) | int getx() { return x; }
    method showx (line 9) | void showx() { cout << x << endl; }
  class derived (line 12) | class derived : public base {
    method sety (line 16) | void sety(int n) { y = n; }
    method sety (line 17) | void sety() { y = getx(); }
    method showy (line 18) | void showy() { cout << y << endl; }
  function main (line 21) | int main() {

FILE: practical_exercises/10_day_practice/day5/inherit_access/protected.cpp
  class B (line 8) | class B {
  class D (line 18) | class D : public B {
    method f (line 20) | void f() {
  function main (line 26) | int main() {

FILE: practical_exercises/10_day_practice/day5/inherit_access/protected_inherit.cpp
  class Base (line 8) | class Base {
    method getx (line 12) | int getx() { return x; }
    method setx (line 15) | void setx(int n) { x = n; }
    method showx (line 16) | void showx() { cout << x << endl; }
  class Derived (line 18) | class Derived : protected Base {
    method sety (line 22) | void sety(int n) { y = n; }
    method sety (line 23) | void sety() { y = getx(); }
    method showy (line 24) | void showy() { cout << y << endl; }
  function main (line 26) | int main() {

FILE: practical_exercises/10_day_practice/day5/inherit_access/public.cpp
  class Base (line 3) | class Base {
    method setx (line 7) | void setx(int n) { x = n; }
    method getx (line 8) | int getx() { return x; }
    method showx (line 9) | void showx() { cout << x << endl; }
  class derived (line 13) | class derived : private Base {
    method sety (line 17) | void sety(int n) { y = n; }
    method sety (line 18) | void sety() { y = getx(); }
    method showy (line 19) | void showy() { cout << y << endl; }
  function main (line 21) | int main() {

FILE: practical_exercises/10_day_practice/day5/rela/rela.cpp
  class A (line 4) | class A {
    method setA (line 8) | void setA(int x) { a = x; }
    method getA (line 9) | int getA() { return a; }
  class B (line 11) | class B : public A {
    method setB (line 15) | void setB(int x) { b = x; }
    method getB (line 16) | int getB() { return b; }
  function f1 (line 18) | void f1(A a, int x) { a.setA(x); }
  function f2 (line 19) | void f2(A *pA, int x) { pA->setA(x); }
  function f3 (line 20) | void f3(A &rA, int x) { rA.setA(x); }
  function main (line 22) | int main() {

FILE: practical_exercises/10_day_practice/day5/rule/direct.cpp
  class A (line 5) | class A {
    method A (line 9) | A(int aa) {
  class B (line 15) | class B : public A {
    method B (line 17) | B(int x) : A(x) { cout << "Constructing B" << endl; }
  class C (line 19) | class C : public B {
    method C (line 21) | C(int y) : B(y) { cout << "Constructing C" << endl; }
  function main (line 23) | int main() {

FILE: practical_exercises/10_day_practice/day5/virtual/example1.cpp
  class A (line 4) | class A {
    method vf (line 6) | void vf() { cout << "I come from class A" << endl; }
  class B (line 8) | class B : public A {}
  class C (line 9) | class C : public A {}
  class D (line 10) | class D : public B, public C {}
  function main (line 12) | int main() {

FILE: practical_exercises/10_day_practice/day5/virtual/example2.cpp
  class A (line 4) | class A {
    method vf (line 6) | void vf() { cout << "I come from class A" << endl; }
  class B (line 8) | class B : virtual public A {}
  class C (line 9) | class C : virtual public A {}
  class D (line 10) | class D : public B, public C {}
  function main (line 12) | int main() {

FILE: practical_exercises/10_day_practice/day5/virtual/init.cpp
  class A (line 4) | class A {
    method A (line 8) | A(int x) {
  class B (line 13) | class B : virtual public A {
    method B (line 15) | B(int i) : A(i) { cout << "Virtual Bass B..." << endl; }
  class C (line 17) | class C : virtual public A {
    method C (line 21) | C(int i) : A(i) {
  class ABC (line 26) | class ABC : public C, public B {
    method ABC (line 29) | ABC(int i, int j, int k)
  function main (line 35) | int main() {

FILE: practical_exercises/10_day_practice/day5/virtual/seq.cpp
  class A (line 5) | class A {
    method A (line 9) | A() { cout << "Constructing A" << endl; }
  class B (line 11) | class B {
    method B (line 13) | B() { cout << "Constructing B" << endl; }
  class B1 (line 15) | class B1 : virtual public B, virtual public A {
    method B1 (line 17) | B1(int i) { cout << "Constructing B1" << endl; }
  class B2 (line 19) | class B2 : public A, virtual public B {
    method B2 (line 21) | B2(int j) { cout << "Constructing B2" << endl; }
  class D (line 23) | class D : public B1, public B2 {
    method D (line 25) | D(int m, int n) : B1(m), B2(n) { cout << "Constructing D" << endl; }
  function main (line 29) | int main() {

FILE: practical_exercises/10_day_practice/day6/abstract_class/main.cpp
  class Figure (line 4) | class Figure {
    method set (line 9) | void set(double i, double j) {
  class Trianle (line 16) | class Trianle : public Figure {
    method area (line 18) | void area() { cout << "三角形面积:" << x * y * 0.5 << endl; }
  class Rectangle (line 20) | class Rectangle : public Figure {
    method area (line 22) | void area() { cout << "这是矩形,它的面积是:" << x * y << endl; }
  function main (line 25) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day6/virtual_func/example.cpp
  class Employee (line 10) | class Employee {
    method Employee (line 12) | Employee(string Name, string id) : name(Name), Id(id) {}
    method string (line 13) | string getName() const { return name; }
    method string (line 14) | string getID() const { return Id; }
    method getSalary (line 15) | virtual float getSalary() const { return 0.0; }
    method print (line 16) | virtual void print() const {                    //输出姓名和身份证号
  class Manager (line 25) | class Manager : public Employee {
    method Manager (line 27) | Manager(string Name, string id, int week) : Employee(Name, id) {
    method getSalary (line 30) | float getSalary() const { return WeeklySalary; }
    method print (line 31) | void print() const { //打印经理姓名、身份证、周薪
  class SaleWorker (line 40) | class SaleWorker : public Employee {
    method SaleWorker (line 42) | SaleWorker(string name, string id, int profit, int x) : Employee(name,...
    method getSalary (line 45) | float getSalary() const { return workerMoney; }
    method print (line 46) | void print() const {
  class HourWorker (line 56) | class HourWorker : public Employee {
    method HourWorker (line 58) | HourWorker(string name, string id, int h) : Employee(name, id) {
    method getSalary (line 61) | float getSalary() const { return TotalMoney; }
    method print (line 62) | void print() const {
  function main (line 72) | int main() {

FILE: practical_exercises/10_day_practice/day6/virtual_func/virtual.cpp
  class Employee (line 9) | class Employee {
  function string (line 25) | string Employee::getName() { return Name; }
  function string (line 26) | string Employee::getId() { return Id; }
  class Manager (line 33) | class Manager : public Employee {
    method Manager (line 35) | Manager(string name, string id, float s = 0.0) : Employee(name, id) {
    method setSalary (line 38) | void setSalary(float s) { weeklySalary = s; }
    method getSalary (line 39) | float getSalary() { return weeklySalary; }
    method print (line 40) | void print() { //打印经理姓名、身份证、周薪
  function main (line 53) | int main() {

FILE: practical_exercises/10_day_practice/day6/virtual_func/virtual_dtor.cpp
  class A (line 5) | class A {
  class B (line 9) | class B : public A {
    method B (line 13) | B(int i) { buf = new char[i]; }
  function main (line 19) | int main() {

FILE: practical_exercises/10_day_practice/day6/virtual_func/virtual_feature.cpp
  class A (line 5) | class A {
    method f (line 7) | void f(int i) { cout << "A::f()" << endl; }
  class B (line 9) | class B : public A {
    method f (line 11) | virtual void f(int i) { cout << "B::f()" << endl; }
  class C (line 13) | class C : public B {
    method f (line 15) | void f(int i) { cout << "C::f()" << endl; }
  class D (line 18) | class D : public C {
    method f (line 20) | void f(int) { cout << "D::f()" << endl; }
  function main (line 22) | int main() {

FILE: practical_exercises/10_day_practice/day6/virtual_func/vis.cpp
  class B (line 4) | class B {
    method f (line 6) | void f() { g(); }
    method g (line 7) | virtual void g() { cout << "B::g"; }
  class D (line 9) | class D : public B {
    method g (line 11) | void g() { cout << "D::g\n"; }
  function main (line 13) | int main() {

FILE: practical_exercises/10_day_practice/day7/binary_operator/friend_operator.cpp
  class Complex (line 17) | class Complex {
    method Complex (line 22) | Complex(double R = 0, double I = 0) : r(R), i(I){}
    method Complex (line 28) | Complex operator+(Complex a, double b) {
    method Complex (line 31) | Complex operator+(double a, Complex b) {
  function Complex (line 38) | Complex operator+(Complex a, Complex b) {
    method Complex (line 22) | Complex(double R = 0, double I = 0) : r(R), i(I){}
    method Complex (line 28) | Complex operator+(Complex a, double b) {
    method Complex (line 31) | Complex operator+(double a, Complex b) {
  function Complex (line 41) | Complex operator-(Complex a, Complex b) {
    method Complex (line 22) | Complex(double R = 0, double I = 0) : r(R), i(I){}
    method Complex (line 28) | Complex operator+(Complex a, double b) {
    method Complex (line 31) | Complex operator+(double a, Complex b) {
  function Complex (line 44) | Complex operator*(Complex a, Complex b) {
    method Complex (line 22) | Complex(double R = 0, double I = 0) : r(R), i(I){}
    method Complex (line 28) | Complex operator+(Complex a, double b) {
    method Complex (line 31) | Complex operator+(double a, Complex b) {
  function Complex (line 50) | Complex operator/(Complex a, Complex b) {
    method Complex (line 22) | Complex(double R = 0, double I = 0) : r(R), i(I){}
    method Complex (line 28) | Complex operator+(Complex a, double b) {
    method Complex (line 31) | Complex operator+(double a, Complex b) {
  function main (line 66) | int main(void) {

FILE: practical_exercises/10_day_practice/day7/binary_operator/operator.cpp
  class Complex (line 5) | class Complex {
    method Complex (line 10) | Complex(double R = 0, double I = 0) : r(R), i(I){}
  function Complex (line 18) | Complex Complex::operator+(Complex b) { return Complex(r + b.r, i + b.i); }
    method Complex (line 10) | Complex(double R = 0, double I = 0) : r(R), i(I){}
  function Complex (line 19) | Complex Complex::operator-(Complex b) { return Complex(r - b.r, i - b.i); }
    method Complex (line 10) | Complex(double R = 0, double I = 0) : r(R), i(I){}
  function Complex (line 21) | Complex Complex::operator*(Complex b) {
    method Complex (line 10) | Complex(double R = 0, double I = 0) : r(R), i(I){}
  function Complex (line 28) | Complex Complex::operator/(Complex b) {
    method Complex (line 10) | Complex(double R = 0, double I = 0) : r(R), i(I){}
  function main (line 45) | int main(void) {

FILE: practical_exercises/10_day_practice/day7/brackets/brac.cpp
  class Time (line 4) | class Time {
    method Time (line 9) | Time(int h = 0, int m = 0, int s = 0) : hh(h), mm(m), ss(s) {}
    method ShowTime (line 15) | void ShowTime() { cout << hh << ":" << mm << ":" << ss << endl; }
  function main (line 17) | int main() {

FILE: practical_exercises/10_day_practice/day7/equal_operator/equal_operator.cpp
  class X (line 5) | class X {
    method X (line 7) | X &operator=(const X &x) {
  function main (line 12) | int main() {

FILE: practical_exercises/10_day_practice/day7/example/example.cpp
  class String (line 6) | class String {
    method ostream (line 11) | ostream &operator<<(ostream &os, const String &s) {
    method istream (line 14) | istream &operator>>(istream &is, String &s) {
    method String (line 19) | const String &operator=(const String &R) {
  function String (line 34) | const String &String::operator+=(const String &R) {
    method ostream (line 11) | ostream &operator<<(ostream &os, const String &s) {
    method istream (line 14) | istream &operator>>(istream &is, String &s) {
    method String (line 19) | const String &operator=(const String &R) {
  function main (line 57) | int main() {

FILE: practical_exercises/10_day_practice/day7/index_parentheses/example.cpp
  class X (line 4) | class X {
  function main (line 23) | int main(void) {

FILE: practical_exercises/10_day_practice/day7/subscript_operator/subscript_operator.cpp
  type Person (line 6) | struct Person { //职工基本信息的结构
  class SalaryManaege (line 10) | class SalaryManaege {
    method SalaryManaege (line 15) | SalaryManaege(int Max = 0) {
    method display (line 34) | void display() {
  function main (line 39) | int main() {

FILE: practical_exercises/10_day_practice/day7/unary_operator/time_counter.cpp
  class Counter (line 5) | class Counter {
    method Counter (line 10) | Counter(int i = 0) : n(i){}
  function Counter (line 17) | Counter Counter::operator++() {
    method Counter (line 10) | Counter(int i = 0) : n(i){}
  function Counter (line 21) | Counter Counter::operator++(int) {
    method Counter (line 10) | Counter(int i = 0) : n(i){}
  function Counter (line 26) | Counter operator--(Counter &c) {
    method Counter (line 10) | Counter(int i = 0) : n(i){}
  function Counter (line 30) | Counter operator--(Counter& c, int) {
    method Counter (line 10) | Counter(int i = 0) : n(i){}
  function main (line 36) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day7/unary_operator/time_increase.cpp
  class Time (line 7) | class Time {
  function Time (line 31) | Time Time::operator++() {
  function Time (line 45) | Time operator--(Time &t) {
  function main (line 60) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day8/class_template/spec.cpp
  class Array (line 8) | class Array {
    method Array (line 13) | Array() {
  function T (line 22) | T &Array<T>::operator[](int i) {
  function main (line 57) | int main() {

FILE: practical_exercises/10_day_practice/day8/class_template/stack.cpp
  class Stack (line 8) | class Stack {
    method Stack (line 14) | Stack() { top = 0; }
    method empty (line 17) | bool empty() {
    method setEmpty (line 23) | void setEmpty() { top = -1; }
    method full (line 24) | bool full() {
  function T (line 44) | T Stack<T, MAXSIZE>::pop() {
  function main (line 52) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day8/func/main.cpp
  function T (line 10) | T Min(T a, T b) { return (a < b) ? a : b; }
  function T (line 15) | T myMin(T a, T b) { return (a < b) ? a : b; }
  function main (line 24) | int main() {

FILE: practical_exercises/10_day_practice/day8/func/max.cpp
  function T (line 5) | T Max(T a, T b) { return (a > b) ? a : b; }
  function main (line 9) | int main() {

FILE: practical_exercises/10_day_practice/day8/func/max_spec.cpp
  function T (line 6) | T Max(T a, T b) { return (a > b) ? a : b; }
  function main (line 15) | int main() {

FILE: practical_exercises/10_day_practice/day8/func/sort.cpp
  function sort (line 8) | void sort(T *a, int n) {
  function display (line 19) | void display(T &a, int n) {
  function main (line 24) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day8/stl/map.cpp
  function main (line 6) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/10_day_practice/day9/exception/1.cpp
  function main (line 4) | int main() {

FILE: practical_exercises/10_day_practice/day9/exception/10.cpp
  class Full (line 5) | class Full {
    method Full (line 9) | Full(int i) : a(i) {}
    method getValue (line 10) | int getValue() { return a; }
  class Empty (line 12) | class Empty {}
  class Stack (line 13) | class Stack {
    method Stack (line 19) | Stack() { top = -1; }
    method push (line 20) | void push(int a) {
    method pop (line 25) | int pop() {
  function main (line 31) | int main() {

FILE: practical_exercises/10_day_practice/day9/exception/2.cpp
  function main (line 4) | int main() {

FILE: practical_exercises/10_day_practice/day9/exception/3.cpp
  function temperature (line 3) | void temperature(int t) {
  function main (line 17) | int main() {

FILE: practical_exercises/10_day_practice/day9/exception/4.cpp
  function temperature (line 3) | void temperature(int t) {
  function main (line 13) | int main() {

FILE: practical_exercises/10_day_practice/day9/exception/5.cpp
  function handler (line 5) | void handler(int n) throw(int, char, double) {
  function main (line 13) | int main() {

FILE: practical_exercises/10_day_practice/day9/exception/6.cpp
  function Errhandler (line 4) | void Errhandler(int n) throw() {
  function main (line 16) | int main() {

FILE: practical_exercises/10_day_practice/day9/exception/7-1.cpp
  class A (line 4) | class A {
    method A (line 8) | A(int i = 0) : a(i) {}
  class B (line 11) | class B {
    method B (line 16) | B(int k) {
  function main (line 27) | int main() {

FILE: practical_exercises/10_day_practice/day9/exception/7.cpp
  function Errhandler (line 5) | void Errhandler(int n) {
  function main (line 15) | int main() {

FILE: practical_exercises/10_day_practice/day9/exception/8.cpp
  class Full (line 5) | class Full {}
  class Empty (line 6) | class Empty {}
  class Stack (line 7) | class Stack {
    method Stack (line 15) | Stack() { top = -1; }
  function main (line 27) | int main() {

FILE: practical_exercises/10_day_practice/day9/exception/9-2.cpp
  class BasicException (line 3) | class BasicException {
    method string (line 5) | virtual string Where() { return "BasicException..."; }
  class FileSysException (line 7) | class FileSysException : public BasicException {
    method string (line 9) | virtual string Where() { return "FileSysException..."; }
  class FileNotFound (line 11) | class FileNotFound : public FileSysException {
    method string (line 13) | virtual string Where() { return "FileNotFound..."; }
  class DiskNotFound (line 15) | class DiskNotFound : public FileSysException {
    method string (line 17) | virtual string Where() { return "DiskNotFound..."; }
  function main (line 19) | int main() {

FILE: practical_exercises/10_day_practice/day9/exception/9.cpp
  class BasicException (line 4) | class BasicException {
  class FileSysException (line 8) | class FileSysException : public BasicException {
  class FileNotFound (line 12) | class FileNotFound : public FileSysException {
  class DiskNotFound (line 16) | class DiskNotFound : public FileSysException {
  function main (line 20) | int main() {

FILE: practical_exercises/key_exercises/array.cpp
  function main (line 5) | int main() {

FILE: practical_exercises/key_exercises/array_template.cpp
  class Array (line 6) | class Array {
    method Array (line 8) | Array() {
  function T (line 21) | T &Array<T>::operator[](int i) {
  function main (line 57) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/key_exercises/bracket_overloading.cpp
  type Person (line 5) | struct Person { //职工基本信息的结构
  class SalaryManaege (line 9) | class SalaryManaege {
    method SalaryManaege (line 14) | SalaryManaege(int Max = 0) {
    method display (line 34) | void display() {
  function main (line 40) | int main() {

FILE: practical_exercises/key_exercises/clock.cpp
  class Clock (line 9) | class Clock {
  function Clock (line 42) | Clock &Clock::operator++() {
  function Clock (line 59) | Clock Clock::operator++(int) {
  function main (line 68) | int main() {

FILE: practical_exercises/key_exercises/func_temp.cpp
  function T (line 6) | T compareMax(T t1, T t2) { return t1 > t2 ? t1 : t2; }
  function main (line 14) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/key_exercises/io_operator.cpp
  class Sales (line 5) | class Sales {
  function Sales (line 23) | Sales &operator<<(ostream &os, Sales &s) {
  function Sales (line 28) | Sales &operator>>(istream &is, Sales &s) {
  function main (line 33) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/key_exercises/io_operator_overload.cpp
  class Sales (line 9) | class Sales {
  function Sales (line 26) | Sales &operator<<(ostream &os, Sales &s) {
  function Sales (line 32) | Sales &operator>>(istream &is, Sales &s) {
  function main (line 37) | int main() {

FILE: practical_exercises/key_exercises/map_insert_look.cpp
  function main (line 7) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/key_exercises/operator_cast.cpp
  class Circle (line 16) | class Circle {
    method Circle (line 21) | Circle(double x1, double y1, double r1) {
  function main (line 30) | int main() {

FILE: practical_exercises/key_exercises/operator_circle.cpp
  class Time (line 4) | class Time {
    method Time (line 9) | Time(int h = 0, int m = 0, int s = 0) : hh(h), mm(m), ss(s) {}
    method ShowTime (line 15) | void ShowTime() { cout << hh << ":" << mm << ":" << ss << endl; }
  function main (line 17) | int main() {

FILE: practical_exercises/key_exercises/output.cpp
  function main (line 6) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/key_exercises/override.cpp
  class Employee (line 6) | class Employee {
    method Employee (line 8) | Employee(const char *name, const char *id) {
    method display (line 14) | void display() { cout << Name << "\t" << Id << endl; }
  class Manager (line 21) | class Manager : public Employee {
    method Manager (line 24) | Manager(const char *name, const char *id, int week) : Employee(name, i...
    method display (line 27) | void display() {
  class SaleWorker (line 36) | class SaleWorker : public Employee {
    method SaleWorker (line 38) | SaleWorker(const char *name, const char *id, int profit, int x)
    method display (line 42) | void display() {
  class HourWorker (line 51) | class HourWorker : public Employee {
    method HourWorker (line 53) | HourWorker(const char *name, const char *id, int h) : Employee(name, i...
    method display (line 56) | void display() {
  function main (line 66) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/key_exercises/read_file.cpp
  class Person (line 8) | class Person {
    method Person (line 10) | Person() {}
    method Person (line 11) | Person(char *name, char *id, int math, int chinese, int english) {
    method display (line 20) | void display() {
  function main (line 34) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/key_exercises/stack.cpp
  class Stack (line 8) | class Stack {
    method Stack (line 10) | Stack() {}
    method init (line 11) | void init() { top = -1; }
    method isFull (line 12) | bool isFull() {
    method isEmpty (line 18) | bool isEmpty() {
  function T (line 40) | T Stack<T, MAXSIZE>::pop() {
  function main (line 49) | int main(int argc, char const *argv[]) {

FILE: practical_exercises/key_exercises/try.cpp
  function fun (line 5) | void fun(int x) {
  function main (line 15) | int main(int argc, char const *argv[]) {

FILE: tool/output/container.cpp
  function main (line 13) | int main() {

FILE: tool/output/output_container.h
  type CHARS (line 32) | enum CHARS {
Condensed preview — 675 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (853K chars).
[
  {
    "path": ".gitignore",
    "chars": 93,
    "preview": "com.sh\nbazel-CPlusPlusThings\nbazel-bin\nbazel-out\nbazel-testlogs\nbazel-cplusplus_bazel\n.vscode"
  },
  {
    "path": "README.md",
    "chars": 12806,
    "preview": "\n- [C++ 那些事](#c-那些事)\n    - [重磅项目](#重磅项目)\n    - [关于作者](#关于作者)\n    - [项目运行](#项目运行)\n      - [方式1: vscode + bazel](#方式1-vsco"
  },
  {
    "path": "README_EN.md",
    "chars": 11167,
    "preview": "# Stories About C Plus Plus\n\nThanks for all the support about << Stories About C ++ >>~~, right now you could open this "
  },
  {
    "path": "WORKSPACE",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "basic_content/abstract/BUILD",
    "chars": 1103,
    "preview": "# you can run some main program, just replace binary name\n# such as: `bazel run basic_content/abstract:interesting_facts"
  },
  {
    "path": "basic_content/abstract/README.md",
    "chars": 2435,
    "preview": "# 纯虚函数和抽象类\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n## 1.纯虚函数与抽象类\n\nC++中的纯虚函数(或抽象函数)是我们没有实现的虚函数!我们只需声明它! 通过声明中赋值0来声明纯虚函"
  },
  {
    "path": "basic_content/abstract/abstract.cpp",
    "chars": 422,
    "preview": "/**\n * @file abstract.cpp\n * @brief\n * 抽象类中:在成员函数内可以调用纯虚函数,在构造函数/析构函数内部不能使用纯虚函数\n * 如果一个类从抽象类派生而来,它必须实现了基类中的所有纯虚函数,才能成为非抽"
  },
  {
    "path": "basic_content/abstract/abstract_base.h",
    "chars": 328,
    "preview": "/**\n * @file abstreact_base.cpp\n * @brief\n * C++中的纯虚函数(或抽象函数)是我们没有实现的虚函数!我们只需声明它!通过声明中赋值0来声明纯虚函数!\n * 纯虚函数:没有函数体的虚函数\n * @"
  },
  {
    "path": "basic_content/abstract/derived_full.cpp",
    "chars": 394,
    "preview": "/**\n * @file derived_full.cpp\n * @brief 完整示例!抽象类由派生类继承实现!\n * @author 光城\n * @version v1\n * @date 2019-07-20\n */\n\n#include"
  },
  {
    "path": "basic_content/abstract/interesting_facts1.cpp",
    "chars": 339,
    "preview": "/**\n * @file interesting_facts1.cpp\n * @brief 纯虚函数使一个类变成抽象类\n * @author 光城\n * @version v1\n * @date 2019-07-20\n */\n\n#inclu"
  },
  {
    "path": "basic_content/abstract/interesting_facts2.cpp",
    "chars": 544,
    "preview": "/**\n * @file interesting_facts2.cpp\n * @brief 抽象类类型的指针和引用\n * @author 光城\n * @version v1\n * @date 2019-07-20\n */\n\n#include"
  },
  {
    "path": "basic_content/abstract/interesting_facts3.cpp",
    "chars": 434,
    "preview": "/**\n * @file interesting_facts3.cpp\n * @brief 如果我们不在派生类中覆盖纯虚函数,那么派生类也会变成抽象类。\n * @author 光城\n * @version v1\n * @date 2019-"
  },
  {
    "path": "basic_content/abstract/interesting_facts4.cpp",
    "chars": 501,
    "preview": "/**\n * @file interesting_facts4.cpp\n * @brief 抽象类可以有构造函数\n * @author 光城\n * @version v1\n * @date 2019-07-20\n */\n\n#include "
  },
  {
    "path": "basic_content/abstract/interesting_facts5.cpp",
    "chars": 593,
    "preview": "\n/**\n * @file interesting_facts5.cpp\n * @brief 构造函数不能是虚函数,而析构函数可以是虚析构函数。\n * 例如:当基类指针指向派生类对象并删除对象时,我们可能希望调用适当的析构函数。如果析构函数"
  },
  {
    "path": "basic_content/abstract/pure_virtual.cpp",
    "chars": 428,
    "preview": "/**\n * @file pure_virtual.cpp\n * @brief 纯虚函数:没有函数体的虚函数\n * 抽象类:包含纯虚函数的类\n *\n * @author 光城\n * @version v1\n * @date 2019-07-"
  },
  {
    "path": "basic_content/assert/BUILD",
    "chars": 294,
    "preview": "# you can run some main program, just replace binary name\n# such as: `bazel run basic_content/assert:ignore_assert`\nload"
  },
  {
    "path": "basic_content/assert/README.md",
    "chars": 913,
    "preview": "# assert那些事\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n\n\n## 1.第一个断言案例\n\n断言,**是宏,而非函数**。\n\nassert 宏的原型定义在 <assert.h>(C)、<ca"
  },
  {
    "path": "basic_content/assert/assert.c",
    "chars": 308,
    "preview": "#include <stdio.h> \n#include <assert.h> \n\nint main() \n{ \n    int x = 7; \n\n    /*  Some big code in between and let's say"
  },
  {
    "path": "basic_content/assert/ignore_assert.c",
    "chars": 189,
    "preview": "/**\n * @file ignore_assert.c\n * @brief 忽略断言\n * @author 光城\n * @version v1\n * @date 2019-07-25\n */\n\n# define NDEBUG // 忽略断"
  },
  {
    "path": "basic_content/bit/BUILD",
    "chars": 146,
    "preview": "# please run `bazel run basic_content/bit:bit`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\")\n\ncc_binary(\n    name = \"bit\","
  },
  {
    "path": "basic_content/bit/README.md",
    "chars": 3672,
    "preview": "## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n## Bit field 是什么?\n\n“ 位域 “ 或 “ 位段 “(Bit field)为一种数据结构,可以把数据以位的形式紧凑的储存,并允许程序员对此结"
  },
  {
    "path": "basic_content/bit/bit.cpp",
    "chars": 352,
    "preview": "#include <iostream>\n\nusing namespace std;\nstruct stuff {\n  unsigned int field1 : 30;\n  unsigned int : 2;\n  unsigned int "
  },
  {
    "path": "basic_content/c_poly/BUILD",
    "chars": 283,
    "preview": "# please run `bazel run basic_content/c_poly:c_examp`\n# please run `bazel run basic_content/c_poly:c++_examp`\nload(\"@rul"
  },
  {
    "path": "basic_content/c_poly/README.md",
    "chars": 637,
    "preview": "# C实现C++的面向对象特性\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n## 1.C++实现案例\n\nC++中的多态:在C++中会维护一张虚函数表,根据赋值兼容规则,我们知道父类的指针或者引用是可"
  },
  {
    "path": "basic_content/c_poly/c++_examp.cpp",
    "chars": 554,
    "preview": "/**\n * @file c++_examp.cpp\n * @brief c++中的多态\n * @author 光城\n * @version v1\n * @date 2019-08-06\n */\n\n#include <iostream>\n\n"
  },
  {
    "path": "basic_content/c_poly/c_examp.c",
    "chars": 597,
    "preview": "/**\n * @file c_examp.c\n * @brief C实现多态\n * @author 光城\n * @version v1\n * @date 2019-08-06\n */\n\n#include <stdio.h>\n\n/// 重定义"
  },
  {
    "path": "basic_content/const/BUILD",
    "chars": 548,
    "preview": "# please run `bazel run basic_content/const:const_function`\n# please run `bazel run basic_content/const:const_num`\nload("
  },
  {
    "path": "basic_content/const/README.md",
    "chars": 7355,
    "preview": "## 关于作者\n\n微信公众号:\n\n![](../img/wechat.jpg)\n\n## 1.const含义\n\n常类型是指使用类型修饰符**const**说明的类型,常类型的变量或对象的值是不能被更新的。\n\n## 2.const作用\n\n+ 可"
  },
  {
    "path": "basic_content/const/class_const/c++11_example/BUILD",
    "chars": 314,
    "preview": "# please run `bazel run basic_content/const/class_const/c++11_example:main`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\", "
  },
  {
    "path": "basic_content/const/class_const/c++11_example/apple.cpp",
    "chars": 357,
    "preview": "#include \"apple.h\"\n#include <iostream>\n\nusing namespace std;\nApple::Apple(int i) {}\nint Apple::add(int num) {\n  take(num"
  },
  {
    "path": "basic_content/const/class_const/c++11_example/apple.h",
    "chars": 240,
    "preview": "#pragma once\n\nclass Apple {\npublic:\n  Apple(int i);\n  // 使用c++11标准编译\n  static const int apple_number = 10;\n  // const in"
  },
  {
    "path": "basic_content/const/class_const/c++11_example/main.cpp",
    "chars": 180,
    "preview": "#include \"apple.h\"\n#include <iostream>\nusing namespace std;\nint main() {\n  Apple a(2);\n  cout << a.getCount() << endl;\n "
  },
  {
    "path": "basic_content/const/class_const/first_example/BUILD",
    "chars": 314,
    "preview": "# please run `bazel run basic_content/const/class_const/first_example:main`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\", "
  },
  {
    "path": "basic_content/const/class_const/first_example/apple.cpp",
    "chars": 366,
    "preview": "#include \"apple.h\"\n#include <iostream>\n\nApple::Apple(int i) : apple_number(i) {}\nint Apple::add(int num) {\n  take(num);\n"
  },
  {
    "path": "basic_content/const/class_const/first_example/apple.h",
    "chars": 179,
    "preview": "#pragma once\n\nclass Apple {\npublic:\n  Apple(int i);\n  const int apple_number;\n  void take(int num) const;\n  int add(int "
  },
  {
    "path": "basic_content/const/class_const/first_example/main.cpp",
    "chars": 181,
    "preview": "#include \"apple.h\"\n#include <iostream>\nusing namespace std;\n\nint main() {\n  Apple a(2);\n  cout << a.getCount() << endl;\n"
  },
  {
    "path": "basic_content/const/class_const/overload_example/BUILD",
    "chars": 439,
    "preview": "# please run `bazel run basic_content/const/class_const/overload_example:main`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary"
  },
  {
    "path": "basic_content/const/class_const/overload_example/apple.cpp",
    "chars": 386,
    "preview": "#include \"apple.h\"\n#include <iostream>\n\nint Apple::apple_number = 10;\n\nApple::Apple(int i) { apple_number = i; }\nint App"
  },
  {
    "path": "basic_content/const/class_const/overload_example/apple.h",
    "chars": 173,
    "preview": "#pragma once\n\nclass Apple {\npublic:\n  Apple(int i);\n  static int apple_number;\n  void take(int num) const;\n  int add();\n"
  },
  {
    "path": "basic_content/const/class_const/overload_example/main.cpp",
    "chars": 201,
    "preview": "#include \"apple.h\"\n#include <iostream>\nusing namespace std;\n\nint main() {\n  Apple a(2);\n  cout << a.getCount() << endl;\n"
  },
  {
    "path": "basic_content/const/class_const/static_example/BUILD",
    "chars": 342,
    "preview": "# please run `bazel run basic_content/const/class_const/static_example:main`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\","
  },
  {
    "path": "basic_content/const/class_const/static_example/apple.cpp",
    "chars": 405,
    "preview": "#include \"apple.h\"\n#include <iostream>\n\nconst int Apple::apple_number = 10;\nint Apple::ap = 666;\nApple::Apple(int i) {}\n"
  },
  {
    "path": "basic_content/const/class_const/static_example/apple.h",
    "chars": 219,
    "preview": "#pragma once\nclass Apple {\npublic:\n  Apple(int i);\n  static int ap; // 在类实现文件中定义并初始化\n  static const int apple_number;\n  "
  },
  {
    "path": "basic_content/const/class_const/static_example/main.cpp",
    "chars": 203,
    "preview": "#include \"apple.h\"\n#include <iostream>\nint main() {\n  Apple a(2);\n  std::cout << a.getCount() << std::endl;\n  std::cout "
  },
  {
    "path": "basic_content/const/const_function.cpp",
    "chars": 167,
    "preview": "#include <iostream>\nusing namespace std;\n\nvoid f(const int i) {\n  i = 10; // error: assignment of read-only parameter ‘i"
  },
  {
    "path": "basic_content/const/const_num.cpp",
    "chars": 149,
    "preview": "#include <iostream>\nusing namespace std;\nint main() {\n  const int b = 10;\n  b = 0; // error\n  const string s = \"hellowor"
  },
  {
    "path": "basic_content/const/extern_const/BUILD",
    "chars": 398,
    "preview": "# please run `bazel run basic_content/const/extern_const:const_file1` and `# please run `bazel run basic_content/const/e"
  },
  {
    "path": "basic_content/const/extern_const/const_file1.cpp",
    "chars": 26,
    "preview": "extern const int ext = 12;"
  },
  {
    "path": "basic_content/const/extern_const/const_file2.cpp",
    "chars": 179,
    "preview": "#include <iostream>\n/**\n * by 光城\n * compile: g++ -o file const_file2.cpp const_file1.cpp\n * execute: ./file\n */\nextern c"
  },
  {
    "path": "basic_content/const/extern_const/file1.cpp",
    "chars": 8,
    "preview": "int ext;"
  },
  {
    "path": "basic_content/const/extern_const/file2.cpp",
    "chars": 168,
    "preview": "#include <iostream>\n/**\n * by 光城\n * compile: g++ -o file file2.cpp file1.cpp\n * execute: ./file\n */\nextern int ext;\nint "
  },
  {
    "path": "basic_content/const/funciton_const/condition1/BUILD",
    "chars": 770,
    "preview": "# please run `bazel run basic_content/const/funciton_const/condition2:condition1`\n# please run `bazel run basic_content/"
  },
  {
    "path": "basic_content/const/funciton_const/condition1/condition1.cpp",
    "chars": 97,
    "preview": "#include <iostream>\nusing namespace std;\n\nint main() {\n  const int *ptr;\n  *ptr = 10; // error\n}\n"
  },
  {
    "path": "basic_content/const/funciton_const/condition1/condition2.cpp",
    "chars": 177,
    "preview": "#include <iostream>\nusing namespace std;\n\nint main() {\n  const int p = 10;\n  // const void *vp = &p;  // const pointer t"
  },
  {
    "path": "basic_content/const/funciton_const/condition1/condition3.cpp",
    "chars": 167,
    "preview": "#include <iostream>\nusing namespace std;\n\nint main() {\n  const int *ptr;\n  int val = 3;\n  ptr = &val; // ok\n  int *ptr1 "
  },
  {
    "path": "basic_content/const/funciton_const/condition2/BUILD",
    "chars": 675,
    "preview": "# please run `bazel run basic_content/const/funciton_const/condition2:condition1`\n# please run `bazel run basic_content/"
  },
  {
    "path": "basic_content/const/funciton_const/condition2/condition1.cpp",
    "chars": 179,
    "preview": "#include <iostream>\nusing namespace std;\nint main() {\n  int num = 0;\n  int *const ptr = &num; // const指针必须初始化!且const指针的指"
  },
  {
    "path": "basic_content/const/funciton_const/condition2/condition2.cpp",
    "chars": 155,
    "preview": "#include <iostream>\nusing namespace std;\nint main() {\n  const int num = 0;\n  int *const ptr = &num; // error! const int*"
  },
  {
    "path": "basic_content/const/funciton_const/condition2/condition3.cpp",
    "chars": 133,
    "preview": "#include <iostream>\nusing namespace std;\nint main() {\n  const int num = 10;\n  const int *const ptr = &num;\n  cout << *pt"
  },
  {
    "path": "basic_content/const/funciton_const/condition3/BUILD",
    "chars": 317,
    "preview": "# please run `bazel run basic_content/const/funciton_const/condition3:condition1`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_bin"
  },
  {
    "path": "basic_content/const/funciton_const/condition3/condition1.cpp",
    "chars": 129,
    "preview": "#include <iostream>\nusing namespace std;\n\nint main() {\n  const int p = 3;\n  const int *const ptr = &p;\n  cout << *ptr <<"
  },
  {
    "path": "basic_content/decltype/BUILD",
    "chars": 194,
    "preview": "# please run `bazel run basic_content/decltype:decltype`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\")\n\ncc_binary(\n    nam"
  },
  {
    "path": "basic_content/decltype/README.md",
    "chars": 2238,
    "preview": "# decltype那些事\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n## 1.基本使用\ndecltype的语法是:\n\n```\ndecltype (expression)\n```\n\n这里的括号是必"
  },
  {
    "path": "basic_content/decltype/decltype.cpp",
    "chars": 814,
    "preview": "#include <iostream>\n#include <vector>\nusing namespace std;\n/**\n * 泛型编程中结合auto,用于追踪函数的返回值类型\n */\ntemplate <typename T>\n\nau"
  },
  {
    "path": "basic_content/enum/BUILD",
    "chars": 475,
    "preview": "# please run `bazel run basic_content/enum:classic_practice`\n# please run `bazel run basic_content/enum:tradition_color`"
  },
  {
    "path": "basic_content/enum/README.md",
    "chars": 2521,
    "preview": "# 从初级到高级的enum那些事\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n\n## 传统行为\n\n\n枚举有如下问题:\n\n- 作用域不受限,会容易引起命名冲突。例如下面无法编译通过的:\n\n```c++"
  },
  {
    "path": "basic_content/enum/classic_practice.cpp",
    "chars": 1070,
    "preview": "#include <iostream>\nusing namespace std;\n/**\n * @brief namespace解决作用域不受限\n */\nnamespace Color {\nenum Type { RED = 15, YEL"
  },
  {
    "path": "basic_content/enum/tradition_color.cpp",
    "chars": 221,
    "preview": "#include <iostream>\nusing namespace std;\n\nenum Color { RED, BLUE };\nenum Feeling { EXCITED, BLUE };\n\nint main() {\n  Colo"
  },
  {
    "path": "basic_content/explicit/BUILD",
    "chars": 288,
    "preview": "# please run `bazel run basic_content/explicit:explicit`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\")\n\n# Don't panic if y"
  },
  {
    "path": "basic_content/explicit/README.md",
    "chars": 270,
    "preview": "# explicit(显式)关键字那些事\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n- explicit 修饰构造函数时,可以防止隐式转换和复制初始化\n- explicit 修饰转换函数时,可以防"
  },
  {
    "path": "basic_content/explicit/explicit.cpp",
    "chars": 1480,
    "preview": "#include <iostream>\n\nusing namespace std;\n\nstruct A {\n  A(int) {}\n  operator bool() const { return true; }\n};\n\nstruct B "
  },
  {
    "path": "basic_content/extern/README.md",
    "chars": 2824,
    "preview": "# extern \"C\"\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n## 1.C++与C编译区别\n\n在C++中常在头文件见到extern \"C\"修饰函数,那有什么作用呢? 是用于C++链接在C语言"
  },
  {
    "path": "basic_content/extern/extern_c/BUILD",
    "chars": 272,
    "preview": "# please run `bazel run basic_content/extern/extern_c:main`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\", \"cc_library\")\n\nc"
  },
  {
    "path": "basic_content/extern/extern_c/add.c",
    "chars": 72,
    "preview": "extern int add(int x,int y);\nint main() {\n    add(2,3);\n    return 0;\n}\n"
  },
  {
    "path": "basic_content/extern/extern_c/add.cpp",
    "chars": 58,
    "preview": "#include \"add.h\"\n\nint add(int x, int y) { return x + y; }\n"
  },
  {
    "path": "basic_content/extern/extern_c/add.h",
    "chars": 73,
    "preview": "#ifndef ADD_H\n#define ADD_H\nextern \"C\" {\nint add(int x, int y);\n}\n#endif\n"
  },
  {
    "path": "basic_content/extern/extern_c++/BUILD",
    "chars": 301,
    "preview": "# please run `bazel run basic_content/extern/extern_c++:main`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\", \"cc_library\")\n"
  },
  {
    "path": "basic_content/extern/extern_c++/add.c",
    "chars": 59,
    "preview": "#include \"add.h\"\n\nint add(int x,int y) {\n    return x+y;\n}\n"
  },
  {
    "path": "basic_content/extern/extern_c++/add.cpp",
    "chars": 139,
    "preview": "#include <iostream>\nusing namespace std;\nextern \"C\" {\n#include \"add.h\"\n}\nint main() {\n  std::cout << add(2, 3) << std::e"
  },
  {
    "path": "basic_content/extern/extern_c++/add.h",
    "chars": 65,
    "preview": "#ifndef ADD_H\n#define ADD_H\nextern int add(int x, int y);\n#endif\n"
  },
  {
    "path": "basic_content/friend/BUILD",
    "chars": 360,
    "preview": "# please run `bazel run basic_content/friend:friend_class`\n# please run `bazel run basic_content/friend:friend_func`\nloa"
  },
  {
    "path": "basic_content/friend/README.md",
    "chars": 1295,
    "preview": "# 友元函数与友元类\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n## 0.概述\n\n友元提供了一种 普通函数或者类成员函数 访问另一个类中的私有或保护成员 的机制。也就是说有两种形式的友元:\n\n(1"
  },
  {
    "path": "basic_content/friend/friend_class.cpp",
    "chars": 255,
    "preview": "#include <iostream>\n\nusing namespace std;\n\nclass A {\npublic:\n  A(int _a) : a(_a){};\n  friend class B;\n\nprivate:\n  int a;"
  },
  {
    "path": "basic_content/friend/friend_func.cpp",
    "chars": 241,
    "preview": "#include <iostream>\n\nusing namespace std;\n\nclass A {\npublic:\n  A(int _a) : a(_a){};\n  friend int geta(A &ca); ///< 友元函数\n"
  },
  {
    "path": "basic_content/func_pointer/BUILD",
    "chars": 209,
    "preview": "# please run `bazel run basic_content/func_pointer:func_pointer`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\")\n\ncc_binary("
  },
  {
    "path": "basic_content/func_pointer/func_pointer.cpp",
    "chars": 495,
    "preview": "/**\n * @file func_pointer.cpp\n * @brief 函数指针的使用!\n * @author 光城\n * @version v1\n * @date 2019-07-20\n */\n\n#include <iostrea"
  },
  {
    "path": "basic_content/inline/BUILD",
    "chars": 461,
    "preview": "# please run `bazel run basic_content/inline:inline_virtual`\n# please run `bazel run basic_content/inline:main`\nload(\"@r"
  },
  {
    "path": "basic_content/inline/README.md",
    "chars": 2134,
    "preview": "# inline那些事\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n## 1.类中内联\n\n头文件中声明方法\n\n```c++\n\nclass A\n{\npublic:\n    void f1(int x)"
  },
  {
    "path": "basic_content/inline/inline.cpp",
    "chars": 860,
    "preview": "#include \"inline.h\"\n#include <iostream>\n\nusing namespace std;\n\n/**\n * @brief\n * inline要起作用,inline要与函数定义放在一起,inline是一种“用于"
  },
  {
    "path": "basic_content/inline/inline.h",
    "chars": 278,
    "preview": "#pragma once\nclass A {\npublic:\n  void f1(int x);\n\n  /**\n   * @brief\n   * 类中定义了的函数是隐式内联函数,声明要想成为内联函数,必须在实现处(定义处)加inline关键"
  },
  {
    "path": "basic_content/inline/inline_virtual.cpp",
    "chars": 595,
    "preview": "#include <iostream>\nusing namespace std;\nclass Base {\npublic:\n  inline virtual void who() { cout << \"I am Base\\n\"; }\n  v"
  },
  {
    "path": "basic_content/macro/BUILD",
    "chars": 347,
    "preview": "# please run `bazel run basic_content/macro:do_while`\n# please run `bazel run basic_content/sig_examp:sig_examp`\nload(\"@"
  },
  {
    "path": "basic_content/macro/README.md",
    "chars": 3465,
    "preview": "# 宏那些事\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n## 1.宏中包含特殊符号\n\n分为几种:`#`,`##`,`\\`\n\n### 1.1 字符串化操作符(#)\n\n**在一个宏中的参数前面使用一个"
  },
  {
    "path": "basic_content/macro/do_while.cpp",
    "chars": 1524,
    "preview": "#include <iostream>\n#include <malloc.h>\n\nusing namespace std;\n#define f1() cout << \"f1()\" << endl;\n#define f2() cout << "
  },
  {
    "path": "basic_content/macro/sig_examp.cpp",
    "chars": 1689,
    "preview": "#include <cstring>\n#include <iostream>\n#include <stdio.h>\n#include <string>\n\nusing namespace std;\n\n///=================="
  },
  {
    "path": "basic_content/maohao/BUILD",
    "chars": 185,
    "preview": "# please run `bazel run basic_content/maohao:maohao`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\")\n\ncc_binary(\n    name = "
  },
  {
    "path": "basic_content/maohao/README.md",
    "chars": 242,
    "preview": "# :: 范围解析运算符那些事\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n- 全局作用域符(::name):用于类型名称(类、类成员、成员函数、变量等)前,表示作用域为全局命名空间\n- 类作用域符"
  },
  {
    "path": "basic_content/maohao/maohao.cpp",
    "chars": 355,
    "preview": "#include <iostream>\nusing namespace std;\n\nint count = 0; // 全局(::)的count\n\nclass A {\npublic:\n  static int count; // 类A的co"
  },
  {
    "path": "basic_content/pointer_refer/BUILD",
    "chars": 389,
    "preview": "# please run `bazel run basic_content/pointer_refer:copy_construct`\n# please run `bazel run basic_content/pointer_refer:"
  },
  {
    "path": "basic_content/pointer_refer/README.md",
    "chars": 3541,
    "preview": "# 引用与指针那些事\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n## 1.引用与指针\n\n总论:\n\n| 引用         | 指针         |\n| ------------ | ----"
  },
  {
    "path": "basic_content/pointer_refer/copy_construct.cpp",
    "chars": 658,
    "preview": "/**\n * @file copy_construct.cpp\n * @brief g++ -o copy_construct copy_construct.cpp -fno-elide-constructors\n * -fno-elide"
  },
  {
    "path": "basic_content/pointer_refer/effec.cpp",
    "chars": 293,
    "preview": "#include <iostream>\nusing namespace std;\nvoid test1(int *p) {\n  *p = 3; //此处应该首先判断p是否为空,为了测试的需要,此处我们没加。\n  return;\n}\n\nvoi"
  },
  {
    "path": "basic_content/sizeof/BUILD",
    "chars": 1124,
    "preview": "# please run `bazel run basic_content/sizeof:blackclass`\n# please run `bazel run basic_content/sizeof:genA`\n# please run"
  },
  {
    "path": "basic_content/sizeof/README.md",
    "chars": 2755,
    "preview": "# 类大小计算\n\n首先来个总结,然后下面给出实际例子,实战!\n\n- 空类的大小为1字节\n- 一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间。\n- 对于包含虚函数的类,不管有多少个虚函数,只有一个虚"
  },
  {
    "path": "basic_content/sizeof/blackclass.cpp",
    "chars": 236,
    "preview": "/**\n * @file blackclass.cpp\n * @brief 空类的大小为1字节\n * @author 光城\n * @version v1\n * @date 2019-07-21\n */\n\n#include <bits/std"
  },
  {
    "path": "basic_content/sizeof/genA.cpp",
    "chars": 356,
    "preview": "/**\n * @file genA.cpp\n * @brief\n * 普通成员函数,大小为1,一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间。\n * @author 光城\n * @version "
  },
  {
    "path": "basic_content/sizeof/geninhe.cpp",
    "chars": 850,
    "preview": "/**\n * @file geninhe.cpp\n * @brief 1.普通单继承,继承就是基类+派生类自身的大小(注意字节对齐)\n * 注意:类的数据成员按其声明顺序加入内存,无访问权限无关,只看声明顺序。\n * 2.虚单继承,派生类继"
  },
  {
    "path": "basic_content/sizeof/moreinhe.cpp",
    "chars": 421,
    "preview": "/**\n * @file moreinhe.cpp\n * @brief 普通多继承与虚函数多继承\n * @author 光城\n * @version v1\n * @date 2019-07-21\n */\n\n#include <iostrea"
  },
  {
    "path": "basic_content/sizeof/morevir.cpp",
    "chars": 330,
    "preview": "/**\n * @file morevir.cpp\n * @brief 对于包含虚函数的类,不管有多少个虚函数,只有一个虚指针,vptr的大小。\n * @author 光城\n * @version v1\n * @date 2019-07-21"
  },
  {
    "path": "basic_content/sizeof/static.cpp",
    "chars": 474,
    "preview": "/**\n * @file static.cpp\n * @brief 静态数据成员\n * 静态数据成员被编译器放在程序的一个global data\n * members中,它是类的一个数据成员,但不影响类的大小。不管这个类产生了多少个实例,还"
  },
  {
    "path": "basic_content/sizeof/virinhe.cpp",
    "chars": 443,
    "preview": "/**\n * @file virnhe.cpp\n * @brief 虚继承\n * @author 光城\n * @version v1\n * @date 2019-07-21\n */\n\n#include <iostream>\n\nusing n"
  },
  {
    "path": "basic_content/sizeof/virmoreinhe.cpp",
    "chars": 434,
    "preview": "/**\n * @file virmoreinhe.cpp\n * @brief 虚函数多继承\n * @author 光城\n * @version v1\n * @date 2019-07-21\n */\n\n#include <iostream>\n"
  },
  {
    "path": "basic_content/static/BUILD",
    "chars": 1052,
    "preview": "# please run `bazel run basic_content/static:nostatic_class`\n# please run `bazel run basic_content/static:static_class`\n"
  },
  {
    "path": "basic_content/static/README.md",
    "chars": 3532,
    "preview": "# static那些事\n\n## 关于作者\n\n微信公众号:\n\n![](../img/wechat.jpg)\n\n当与不同类型一起使用时,Static关键字具有不同的含义。我们可以使用static关键字:\n\n**静态变量:** 函数中的变量,类中"
  },
  {
    "path": "basic_content/static/nostatic_class.cpp",
    "chars": 277,
    "preview": "#include <iostream>\nusing namespace std;\n\nclass Apple {\n  int i;\n\npublic:\n  Apple() {\n    i = 0;\n    cout << \"Inside Con"
  },
  {
    "path": "basic_content/static/static_class.cpp",
    "chars": 284,
    "preview": "#include <iostream>\nusing namespace std;\n\nclass Apple {\n  int i;\n\npublic:\n  Apple() {\n    i = 0;\n    cout << \"Inside Con"
  },
  {
    "path": "basic_content/static/static_demo.cpp",
    "chars": 357,
    "preview": "// the use of static Static\n// variables in a Function\n#include <iostream>\n#include <string>\nusing namespace std;\n\nvoid "
  },
  {
    "path": "basic_content/static/static_error_variable.cpp",
    "chars": 280,
    "preview": "// variables inside a class\n\n#include <iostream>\nusing namespace std;\n\nclass Apple {\npublic:\n  static int i;\n\n  Apple(){"
  },
  {
    "path": "basic_content/static/static_funciton.cpp",
    "chars": 246,
    "preview": "#include <iostream>\nusing namespace std;\n\nclass Apple {\npublic:\n  // static member function\n  static void printMsg() { c"
  },
  {
    "path": "basic_content/static/static_variable.cpp",
    "chars": 229,
    "preview": "// variables inside a class\n\n#include <iostream>\nusing namespace std;\n\nclass GfG {\npublic:\n  static int i;\n\n  GfG(){\n   "
  },
  {
    "path": "basic_content/struct/BUILD",
    "chars": 706,
    "preview": "# please run `bazel run basic_content/struct:ext_struct_func`\n# please run `bazel run basic_content/struct:struct_func_f"
  },
  {
    "path": "basic_content/struct/README.md",
    "chars": 4167,
    "preview": "# 一文搞懂C和C++中struct\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n## 1.C中struct\n\n- 在C中struct只单纯的用作数据的复合类型,也就是说,在结构体声明中只能将数据成"
  },
  {
    "path": "basic_content/struct/ext_struct_func.cpp",
    "chars": 612,
    "preview": "#include <iostream>\n#include <stdio.h>\nusing namespace std;\nstruct Base {\n  int v1;\n  //    private:   //error!\n  int v3"
  },
  {
    "path": "basic_content/struct/struct_func.c",
    "chars": 474,
    "preview": "#include <stdio.h>\n\nstruct Base\n{ // public\n    int v1;\n    //    public:      //error\n    int v2;\n    // private:\n    i"
  },
  {
    "path": "basic_content/struct/struct_func.cpp",
    "chars": 384,
    "preview": "#include <iostream>\n#include <stdio.h>\n\nstruct Base {\n  int v1;\n  //    private:   //error!\n  int v3;\n\npublic: // 显示声明pu"
  },
  {
    "path": "basic_content/struct/struct_func_func.cpp",
    "chars": 651,
    "preview": "#include <iostream>\n#include <stdio.h>\n\nstruct Base {\n  int v1;\n  //    private:   //error!\n  int v3;\n\npublic: // 显示声明pu"
  },
  {
    "path": "basic_content/struct_class/README.md",
    "chars": 307,
    "preview": "# struct与class区别\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n关于C与C++中struct内容:见[struct那些事](../struct)\n\n总的来说,struct 更适合看成是"
  },
  {
    "path": "basic_content/this/BUILD",
    "chars": 183,
    "preview": "# please run `bazel run basic_content/this:person`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\")\n\ncc_binary(\n    name = \"p"
  },
  {
    "path": "basic_content/this/README.md",
    "chars": 1876,
    "preview": "# this指针那些事\n\n## 关于作者\n\n微信公众号:\n\n![](../img/wechat.jpg)\n\n## 1.this指针\n\n相信在坐的很多人,都在学Python,对于Python来说有self,类比到C++中就是this指针,那么"
  },
  {
    "path": "basic_content/this/person.cpp",
    "chars": 543,
    "preview": "#include <cstring>\n#include <iostream>\n\nusing namespace std;\nclass Person {\npublic:\n  typedef enum { BOY = 0, GIRL } Sex"
  },
  {
    "path": "basic_content/union/BUILD",
    "chars": 181,
    "preview": "# please run `bazel run basic_content/union:union`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\")\n\ncc_binary(\n    name = \"u"
  },
  {
    "path": "basic_content/union/README.md",
    "chars": 320,
    "preview": "# UNION那些事\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n联合(union)是一种节省空间的特殊的类,一个 union 可以有多个数据成员,但是在任意时刻只有一个数据成员可以有值。当某个成员"
  },
  {
    "path": "basic_content/union/union.cpp",
    "chars": 690,
    "preview": "/**\n * @file union.cpp\n * @brief UNION\n * @author 光城\n * @version v1\n * @date 2019-08-06\n */\n\n#include <iostream>\n/**\n * "
  },
  {
    "path": "basic_content/using/BUILD",
    "chars": 780,
    "preview": "# please run `bazel run basic_content/using:derived_base`\n# please run `bazel run basic_content/using:using_derived`\n# p"
  },
  {
    "path": "basic_content/using/README.md",
    "chars": 1948,
    "preview": "# using那些事\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n## 基本使用\n\n局部与全局using,具体操作与使用见下面案例:\n\n```c++\n#include <iostream>\n#defi"
  },
  {
    "path": "basic_content/using/derived_base.cpp",
    "chars": 758,
    "preview": "#include <iostream>\n\nusing namespace std;\n\nclass Base1 {\npublic:\n  Base1() : value(10) {}\n  virtual ~Base1() {}\n  void t"
  },
  {
    "path": "basic_content/using/using_derived.cpp",
    "chars": 431,
    "preview": "/**\n * @file using_derived.cpp\n * @brief 函数重装\n * @author 光城\n * @version v1\n * @date 2019-08-07\n */\n\n#include <iostream>\n"
  },
  {
    "path": "basic_content/using/using_global.cpp",
    "chars": 612,
    "preview": "/**\n * @file using_global.cpp\n * @brief using各种使用\n * @author 光城\n * @version v1\n * @date 2019-08-07\n */\n\n#include <iostre"
  },
  {
    "path": "basic_content/using/using_typedef.cpp",
    "chars": 597,
    "preview": "/**\n * @file using_typedef.cpp\n * @brief bazel run basic_content/using:using_typedef\n * 取代typedef,使用using来定义别名\n * @autho"
  },
  {
    "path": "basic_content/virtual/README.md",
    "chars": 2577,
    "preview": "# virtual那些事\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n## 1.虚函数与运行多态\n\n对应的代码:[emp.cpp](./set1/emp.cpp)\n\n**虚函数的调用取决于指向或者引"
  },
  {
    "path": "basic_content/virtual/set1/BUILD",
    "chars": 182,
    "preview": "# please run `bazel run basic_content/virtual/set1:emp`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\")\n\ncc_binary(\n    name"
  },
  {
    "path": "basic_content/virtual/set1/emp.cpp",
    "chars": 1212,
    "preview": "#include <iostream>\nusing namespace std;\n\nclass Employee {\npublic:\n  virtual void raiseSalary() { cout << 0 << endl; }\n\n"
  },
  {
    "path": "basic_content/virtual/set2/BUILD",
    "chars": 206,
    "preview": "# please run `bazel run basic_content/virtual/set2:default_arg`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\")\n\ncc_binary(\n"
  },
  {
    "path": "basic_content/virtual/set2/default_arg.cpp",
    "chars": 507,
    "preview": "/**\n * @file first_example.cpp\n * @brief 虚函数中默认参数\n * 规则:虚函数是动态绑定的,默认参数是静态绑定的。默认参数的使用需要看指针或者应用本身的类型,而不是对象的类型!\n * @author "
  },
  {
    "path": "basic_content/virtual/set3/BUILD",
    "chars": 1393,
    "preview": "# please run `bazel run //basic_content/virtual/set3:copy_consrtuct`\n# please run `bazel run //basic_content/virtual/set"
  },
  {
    "path": "basic_content/virtual/set3/copy_consrtuct.cpp",
    "chars": 574,
    "preview": "#include <iostream>\nusing namespace std;\n\nclass Base {\npublic:\n};\n\nclass Derived : public Base {\npublic:\n  Derived() { c"
  },
  {
    "path": "basic_content/virtual/set3/full_virde.cpp",
    "chars": 621,
    "preview": "/**\n * @file full_virde.cpp\n * @brief 将基类的析构函数声明为虚函数\n * 输出结果:\n *      Constructing base\n *      Constructing derived\n * "
  },
  {
    "path": "basic_content/virtual/set3/inline_virtual.cpp",
    "chars": 595,
    "preview": "#include <iostream>\nusing namespace std;\nclass Base {\npublic:\n  inline virtual void who() { cout << \"I am Base\\n\"; }\n  v"
  },
  {
    "path": "basic_content/virtual/set3/static_error.cpp",
    "chars": 341,
    "preview": "/**\n * @file static_error.cpp\n * @brief 静态函数不可以声明为虚函数,同时也不能被const和volatile关键字修饰!\n * 原因如下:\n * static成员函数不属于任何类对象或类实例,所以即使"
  },
  {
    "path": "basic_content/virtual/set3/vir_con.cpp",
    "chars": 3350,
    "preview": "/**\n * @file vir_con.cpp\n * @brief\n * 构造函数不可以声明为虚函数。同时除了inline之外,构造函数不允许使用其它任何关键字。\n *\n * 为什么构造函数不可以为虚函数?\n *\n * 尽管虚函数表vta"
  },
  {
    "path": "basic_content/virtual/set3/vir_de.cpp",
    "chars": 654,
    "preview": "/**\n * @file vir_de.cpp\n * @brief 派生类的析构函数没有被调用!\n * 输出结果:\n *      Constructing base\n *      Constructing derived\n *     "
  },
  {
    "path": "basic_content/virtual/set3/virtual_function.cpp",
    "chars": 562,
    "preview": "/**\n * @file virtual_function.cpp\n * @brief 虚函数可以被私有化,但有一些细节需要注意。\n * 基类指针指向继承类对象,则调用继承类对象的函数;\n * int main()必须声明为Base类的友元"
  },
  {
    "path": "basic_content/virtual/set3/virtual_function1.cpp",
    "chars": 305,
    "preview": "#include <iostream>\nusing namespace std;\n\nclass Derived;\n\nclass Base {\npublic:\n  virtual void fun() { cout << \"Base Fun\""
  },
  {
    "path": "basic_content/virtual/set3/virtual_inline.cpp",
    "chars": 717,
    "preview": "/**\n * @file virtual_inline.cpp\n * @brief 通常类成员函数都会被编译器考虑是否进行内联。\n * 但通过基类指针或者引用调用的虚函数必定不能被内联。\n * 当然,实体对象调用虚函数或者静态调用时可以被内"
  },
  {
    "path": "basic_content/virtual/set4/BUILD",
    "chars": 185,
    "preview": "# please run `bazel run basic_content/virtual/set4:rtti`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\")\n\ncc_binary(\n    nam"
  },
  {
    "path": "basic_content/virtual/set4/rtti.cpp",
    "chars": 836,
    "preview": "/**\n * @file rtti.cpp\n * @brief\n * 在面向对象程序设计中,有时我们需要在运行时查询一个对象是否能作为某种多态类型使用。与Java的instanceof,以及C#的as、is运算符类似,C++提供了dynam"
  },
  {
    "path": "basic_content/virtual/set4/warn_rtti.cpp",
    "chars": 283,
    "preview": "// 在使用时需要注意:被转换对象obj的类型T1必须是多态类型,即T1必须公有继承自其它类,或者T1拥有虚函数(继承或自定义)。若T1为非多态类型,使用dynamic_cast会报编译错误。\n\n// A为非多态类型\n\nclass A {}"
  },
  {
    "path": "basic_content/volatile/BUILD",
    "chars": 349,
    "preview": "# please run `bazel run basic_content/volatile:noopt_vola`\n# please run `bazel run basic_content/volatile:volatile`\nload"
  },
  {
    "path": "basic_content/volatile/README.md",
    "chars": 2637,
    "preview": "## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n## 1.volatile\n\n被 `volatile` 修饰的变量,在对其进行读写操作时,会引发一些**可观测的副作用**。而这些可观测的副作用,是由**程"
  },
  {
    "path": "basic_content/volatile/noopt_vola.cpp",
    "chars": 269,
    "preview": "/* Compile code without optimization option */\n#include <stdio.h>\nint main(void) {\n  const int local = 10;\n  int *ptr = "
  },
  {
    "path": "basic_content/volatile/volatile.cpp",
    "chars": 276,
    "preview": "/* Compile code with optimization option */\n#include <stdio.h>\n\nint main(void) {\n  const volatile int local = 10;\n  int "
  },
  {
    "path": "basic_content/vptr_vtable/BUILD",
    "chars": 187,
    "preview": "# please run `bazel run basic_content/vptr_vtable:vptr1`\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\")\n\ncc_binary(\n    nam"
  },
  {
    "path": "basic_content/vptr_vtable/README.md",
    "chars": 5485,
    "preview": "# 深入浅出C++虚函数的vptr与vtable\n\n## 关于作者:\n\n个人公众号:\n\n![](../img/wechat.jpg)\n\n\n\n## 1.基础理论\n\n为了实现虚函数,C ++使用一种称为虚拟表的特殊形式的后期绑定。该虚拟表是用于"
  },
  {
    "path": "basic_content/vptr_vtable/vptr1.cpp",
    "chars": 1704,
    "preview": "#include <iostream>\n#include <stdio.h>\nusing namespace std;\n\n/**\n * @brief 函数指针\n */\ntypedef void (*Fun)();\n\n/**\n * @brie"
  },
  {
    "path": "codingStyleIdioms/1_classInitializers/1.1_nest.cpp",
    "chars": 1094,
    "preview": "/* 1.1_类之间嵌套.cpp */\n//\n// Created by light on 19-12-9.\n//\n\n#include <iostream>\n\nclass Animal {\npublic:\n    Animal() {\n  "
  },
  {
    "path": "codingStyleIdioms/1_classInitializers/1.2_nodefault_ctor.cpp",
    "chars": 881,
    "preview": "/* 1.2_无默认构造的继承.cpp */\n//\n// Created by light on 19-12-9.\n//\n#include <iostream>\nclass Animal {\npublic:\n    Animal(int a"
  },
  {
    "path": "codingStyleIdioms/1_classInitializers/1.3_const.cpp",
    "chars": 375,
    "preview": "/* 1.3_类中const数据成员、引用数据成员.cpp */\n//\n// Created by light on 19-12-9.\n//\n\n#include <iostream>\n\nclass Animal {\npublic:\n    "
  },
  {
    "path": "codingStyleIdioms/1_classInitializers/BUILD",
    "chars": 756,
    "preview": "# please run `bazel run //codingStyleIdioms/1_classInitializers:1.2_nodefault_ctor`\n# please run `bazel run //codingStyl"
  },
  {
    "path": "codingStyleIdioms/1_classInitializers/README.md",
    "chars": 3497,
    "preview": "# 初始化列表与赋值\n\n- const成员的初始化只能在构造函数初始化列表中进行\n- 引用成员的初始化也只能在构造函数初始化列表中进行\n- 对象成员(对象成员所对应的类没有默认构造函数)的初始化,也只能在构造函数初始化列表中进行\n\n## 类"
  },
  {
    "path": "codingStyleIdioms/1_classInitializers/initializer.cpp",
    "chars": 260,
    "preview": "/* initializer.cpp */\n//\n// Created by light on 19-12-9.\n//\n\n#include <iostream>\n\nusing namespace std;\n\nclass A {\npublic"
  },
  {
    "path": "codingStyleIdioms/2_enumclass/BUILD",
    "chars": 208,
    "preview": "# please run `bazel run //codingStyleIdioms/2_enumclass:namespace`\n\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\")\n\ncc_bina"
  },
  {
    "path": "codingStyleIdioms/2_enumclass/README.md",
    "chars": 1101,
    "preview": "# C++惯用法之enum class\n\n在Effective modern C++中Item 10: Prefer scoped enums to unscoped enum,调到要用有范围的enum class代替无范围的enum。\n\n"
  },
  {
    "path": "codingStyleIdioms/2_enumclass/namespace.cpp",
    "chars": 572,
    "preview": "//\n// Created by light on 19-12-9.\n//\n\n#include <iostream>\n\nusing namespace std;\n// 在创建枚举时,将它们放在名称空间中,以便可以使用有意义的名称访问它们:\n"
  },
  {
    "path": "codingStyleIdioms/3_RAII/BUILD",
    "chars": 1003,
    "preview": "# please run `bazel run //codingStyleIdioms/3_RAII:RAII_fstram`\n# please run `bazel run //codingStyleIdioms/3_RAII:c++_e"
  },
  {
    "path": "codingStyleIdioms/3_RAII/RAII.cpp",
    "chars": 1595,
    "preview": "#include <iostream>\n#include <mutex>\n#include <fstream>\nusing namespace std;\n// RAII 资源获取即初始化,例1\n\nenum class shape_type "
  },
  {
    "path": "codingStyleIdioms/3_RAII/RAII.md",
    "chars": 8052,
    "preview": "# C++惯用法之消除垃圾收集器-资源获取即初始化方法(RAII)\n\n## 0.导语\n\n在C语言中,有三种类型的内存分配:静态、自动和动态。静态变量是嵌入在源文件中的常数,因为它们有已知的大小并且从不改变,所以它们并不那么有趣。自动分配可以"
  },
  {
    "path": "codingStyleIdioms/3_RAII/RAII_fstram.cpp",
    "chars": 706,
    "preview": "//\n// Created by light on 19-12-9.\n//\n#include <iostream>\n#include <fstream>\n\n// RAII 资源获取即初始化,例2\n\n// C ++保证在对象超出范围时调用析构"
  },
  {
    "path": "codingStyleIdioms/3_RAII/c++_example.cpp",
    "chars": 291,
    "preview": "//\n// Created by light on 19-12-12.\n//\n#include <iostream>\nint main() {\n    std::string str = std::string (\"toptal\");\n  "
  },
  {
    "path": "codingStyleIdioms/3_RAII/c++_example1.cpp",
    "chars": 2020,
    "preview": "//\n// Created by light on 19-12-12.\n//\n#include <iostream>\n#include <vector>\n#include <cstring>\n#include <fstream>\n\nusin"
  },
  {
    "path": "codingStyleIdioms/3_RAII/c++_example2.cpp",
    "chars": 835,
    "preview": "//\n// Created by light on 19-12-12.\n//\n#include <iostream>\n#include <vector>\n#include <cstring>\n#include <fstream>\n#incl"
  },
  {
    "path": "codingStyleIdioms/3_RAII/c_example.cpp",
    "chars": 374,
    "preview": "//\n// Created by light on 19-12-12.\n//\n#include <stdio.h>\n#include <string.h>\n#include <malloc.h>\nint main() {\n    char "
  },
  {
    "path": "codingStyleIdioms/4_copy-swap/BUILD",
    "chars": 226,
    "preview": "# please run `bazel run //codingStyleIdioms/4_copy-swap:copy-swapAndADL`\n\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\")\n\nc"
  },
  {
    "path": "codingStyleIdioms/4_copy-swap/README.md",
    "chars": 4094,
    "preview": "> 为什么我们需要复制和交换习惯?\n\n任何管理资源的类(包装程序,如智能指针)都需要实现big three。尽管拷贝构造函数和析构函数的目标和实现很简单。\n\n但是复制分配运算符无疑是最细微和最困难的。\n\n> 应该怎么做?需要避免什么陷阱?\n"
  },
  {
    "path": "codingStyleIdioms/4_copy-swap/copy-swapAndADL.cpp",
    "chars": 3283,
    "preview": "//\n// Created by light on 19-12-9.\n//\n#include <iostream>\n\n// copy and swap : https://stackoverflow.com/questions/327954"
  },
  {
    "path": "codingStyleIdioms/5_pImpl/BUILD",
    "chars": 502,
    "preview": "# please run `bazel run //codingStyleIdioms/5_pImpl:pimpl`\n# please run `bazel run //codingStyleIdioms/5_pImpl:pimplTime"
  },
  {
    "path": "codingStyleIdioms/5_pImpl/README.md",
    "chars": 934,
    "preview": "# C++惯用法之pImpl\n\n“指向实现的指针”或“pImpl”是一种 C++ 编程技巧,它将类的实现细节从对象表示中移除,放到一个分离的类中,并以一个不透明的指针进行访问。\n\n使用pImpl惯用法的原因如下:\n\n考虑如下例子:\n\n```"
  },
  {
    "path": "codingStyleIdioms/5_pImpl/noPimpl.cpp",
    "chars": 201,
    "preview": "#include <iostream>\n#include <vector>\nusing namespace std;\n\nclass C {\n    vector<int> v;\n    string s;\n};\nclass D {\n    "
  },
  {
    "path": "codingStyleIdioms/5_pImpl/pimpl.cpp",
    "chars": 522,
    "preview": "//\n// Created by light on 19-12-9.\n//\n\n#include <iostream>\nusing namespace std;\n\n// pImpl: Pointer-to-Implementation\n\ncl"
  },
  {
    "path": "codingStyleIdioms/5_pImpl/pimplTime.cpp",
    "chars": 257,
    "preview": "#include <iostream>\n#include <vector>\nusing namespace std;\n\nclass C {\n    vector<int> v;\n    string s;\n};\nclass D {\n    "
  },
  {
    "path": "codingStyleIdioms/5_pImpl/pimplTime.h",
    "chars": 194,
    "preview": "#include <iostream>\n#include <vector>\nusing namespace std;\n\nclass C {\n    vector<int> v;\n    string s;\n};\nclass D {\n    "
  },
  {
    "path": "codingStyleIdioms/README.md",
    "chars": 376,
    "preview": "# 你最喜欢的c++编程风格惯用法是什么?\n\n在stackoverflow上找到了一篇文章,写的蛮好的,地址如下:\n\n> https://stackoverflow.com/questions/276173/what-are-your-fa"
  },
  {
    "path": "concurrency/Threading_In_CPlusPlus/1.thread/BUILD",
    "chars": 377,
    "preview": "# please run `bazel run //concurrency/Threading_In_CPlusPlus/1.thread:intro`\n# please run `bazel run //concurrency/Threa"
  },
  {
    "path": "concurrency/Threading_In_CPlusPlus/1.thread/intro.cpp",
    "chars": 891,
    "preview": "//\n// Created by light on 20-1-31.\n//\n\n#include <iostream>\n#include <chrono>\n\nusing namespace std::chrono;\nusing namespa"
  },
  {
    "path": "concurrency/Threading_In_CPlusPlus/1.thread/thread.cpp",
    "chars": 1045,
    "preview": "//\n// Created by light on 20-1-31.\n//\n\n#include <iostream>\n#include <thread>\n#include <chrono>\n\nusing namespace std::chr"
  },
  {
    "path": "concurrency/Threading_In_CPlusPlus/2.create_type/1.function_pointer.cpp",
    "chars": 335,
    "preview": "//\n// Created by light on 20-1-31.\n//\n\n// 1.函数指针\n#include <thread>\n#include <iostream>\n\nusing namespace std;\n\nvoid fun(i"
  },
  {
    "path": "concurrency/Threading_In_CPlusPlus/2.create_type/2.lambda_function.cpp",
    "chars": 530,
    "preview": "//\n// Created by light on 20-1-31.\n//\n\n// 1.函数指针\n#include <thread>\n#include <iostream>\n\nusing namespace std;\n\n// 注意:如果我们"
  },
  {
    "path": "concurrency/Threading_In_CPlusPlus/2.create_type/3.functor.cpp",
    "chars": 327,
    "preview": "//\n// Created by light on 20-1-31.\n//\n\n\n#include <thread>\n#include <iostream>\n\nusing namespace std;\n\n// 3.functor (Funci"
  },
  {
    "path": "concurrency/Threading_In_CPlusPlus/2.create_type/4.no_static_member_function.cpp",
    "chars": 340,
    "preview": "//\n// Created by light on 20-1-31.\n//\n\n\n#include <thread>\n#include <iostream>\n\nusing namespace std;\n\n// 4.Non-static mem"
  },
  {
    "path": "concurrency/Threading_In_CPlusPlus/2.create_type/5.static_member_function.cpp",
    "chars": 332,
    "preview": "//\n// Created by light on 20-1-31.\n//\n\n\n#include <thread>\n#include <iostream>\n\nusing namespace std;\n\n// 4.Non-static mem"
  },
  {
    "path": "concurrency/Threading_In_CPlusPlus/2.create_type/BUILD",
    "chars": 1101,
    "preview": "# please run `bazel run //concurrency/Threading_In_CPlusPlus/2.create_type:4.no_static_member_function`\n# please run `ba"
  }
]

// ... and 475 more files (download for full content)

About this extraction

This page contains the full source code of the Light-City/CPlusPlusThings GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 675 files (745.6 KB), approximately 287.0k tokens, and a symbol index with 1846 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!