https://en.cppreference.com/w/
https://www.youtube.com/watch?v=H4s55GgAg0I&list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb&index=7
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#main
C++ Linker Works C++中 #include就代表把文件,copy到对应的文件中,如果不用下面的内联,就会爆出重复的Log方法。
inline,只copy方法的内容,不会copy方法体,像这样的
1 2 3 4 5 6 void initLog () { Log ("Init log" ); 内联后被 std::cout << message << std::endl; 替换 }
Log.h
1 inline void Log (const char * message) ;
Log.cpp
1 2 3 4 5 6 7 8 9 #include <iostream> #include "Log.h" void initLog () { Log ("Init log" ); }void Log (const char *message) { std::cout << message << std::endl; }
Math.cpp
1 2 3 4 5 6 7 8 9 10 11 #include <iostream> #include "Log.h" static int multiply (int a, int b) { Log ("multiply" ); return a * b; }int main () { std::cout << multiply (5 ,8 ) <<std::endl; }
copy all contents and paste it into that c++ file.
pragma oncehttps://www.youtube.com/watch?v=9RJTQmK0YPI&list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb&index=11
Log.h
1 2 void Log (const char * message) ;void initLog () ;
Math.cpp
1 2 3 int main () { initLog (); }
Pointer 1 2 3 4 5 6 7 int a = 5 ; int * pStr = &a; *pStr = 10 ; LOG (a)
output : 10
REFERENCES 1 2 3 4 5 6 7 8 9 void increment (int value) { value ++; }int main () { int a = 5 ; increment (a); LOG (a); }
output: 5 可以看到,a数值没有增加
指针传值 1 2 3 4 5 6 7 8 9 void increment (int * value) { (*value) ++; }int main () { int a = 5 ; increment (&a); LOG (a) }
output : 6
reference demo1
1 2 3 4 5 6 7 8 9 void increment (int & value) { value ++; }int main () { int a = 5 ; increment (a); LOG (a) }
output : 6 可以看到,传递引用,操作的是同一个内存地址
demo2
1 2 3 4 5 6 int a = 5 ;int b = 8 ;int & ref = a; ref = b; LOG (a)LOG (b)
output: 8 8
操作指针
1 2 3 4 5 6 7 8 9 10 11 int main () { int a = 5 ; int b = 8 ; int * ref = &a; *ref = 2 ; ref = &b; *ref = 1 ; LOG (a) LOG (b) }
output , 2 , 1
CLASSES move() outside class 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Player {public : int x, y; int speed; };void move (Player& player,int xa ,int ya) { player.x += xa * player.speed; player.y += ya * player.speed; }int main () { Player player; player.x = 5 ; player.speed = 10 ; move (player,1 ,-1 ); LOG (player.x) }
move() inside class 可以看到player不需要再传入了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Player {public : int x, y; int speed; void move (int xa, int ya) { x += xa * speed; y += ya * speed; } };int main () { Player player; player.x = 5 ; player.speed = 10 ; player.move (1 , -1 ); LOG (player.x) }
CLASSES vs STRUCTS 没什么区别, c++为了兼容c struct is publicly defaultly class is private defaultly
Write a C++ Class 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 #include <iostream> class Log {public : const int LogLevelError = 0 ; const int LogLevelWarning = 1 ; const int LogLevelInfo = 2 ;private : int m_LogLevel = LogLevelInfo;public : void setLevel (int level) { m_LogLevel = level; } void error (const char *message) { if (m_LogLevel >= LogLevelError) { std::cout << "[error]:" << message << std::endl; } } void warn (const char *message) { if (m_LogLevel >= LogLevelWarning){ std::cout << "[WARNING]:" << message << std::endl; } } void info (const char *message) { if (m_LogLevel >= LogLevelInfo){ std::cout << "[info]:" << message << std::endl; } } };int main () { Log log; log.setLevel (log.LogLevelWarning); log.warn ("Hello!" ); log.error ("Hello!" ); log.info ("Hello!" ); }
static static variable is onnly going to visible to that c++file that you have declared in .
为了避免global variable 产生的问题。 static.cpp
1 static int s_Variable = 10 ;
main.cpp
1 2 3 4 int s_Variable = 5 ;int main () { std::cout<<s_Variable <<std::endl; }
output 5
或者 extern
static.cpp
1 static int s_Variable = 10 ;
main.cpp
1 2 3 4 extern int s_Variable;int main () { std::cout<<s_Variable <<std::endl; }
output : 10
Static for Classes and Structs global instance for that class dont have class instance
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 struct Entity { int x, y; void print () { std::cout << x << " , " << y << std::endl; } };int main () { Entity e; e.x = 2 ; e.y = 3 ; Entity e1 = {5 , 8 }; e.print (); e1.print (); }
output : 2 , 3 5 , 8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 struct Entity { static int x, y; void print () { std::cout << x << " , " << y << std::endl; } };int Entity::x;int Entity::y;int main () { Entity e; e.x = 2 ; e.y = 3 ; Entity e1; e1.x = 5 ; e1.y = 8 ; e.print (); e1.print (); }
output: 5 , 8 5 , 8
当我们设置 static int x, y; // setting static only one instance of those tow vairables acrossall instances of classed which means when we changed second entity’s x ,y ; e and e1 pointing to the same memory
so we can refer to them like below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 struct Entity { static int x, y; void print () { std::cout << x << " , " << y << std::endl; } };int Entity::x;int Entity::y;int main () { Entity e; Entity::x = 2 ; Entity::y = 3 ; Entity e1; Entity::x = 5 ; Entity::y = 8 ; e.print (); e1.print (); }
output: 5 , 8 5 , 8
class static method 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 struct Entity { static int x, y; static void print () { std::cout << x << " , " << y << std::endl; } };int Entity::x;int Entity::y;int main () { Entity e; Entity::x = 2 ; Entity::y = 3 ; Entity e1; Entity::x = 5 ; Entity::y = 8 ; Entity::print (); Entity::print (); }
output: 5 , 8 5 , 8
static method cannot access non static variables. casue static method doens have a class instance.
and it works like this , it knows which entitiy is.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 struct Entity { static int x, y; };static void print (Entity e) { std::cout << e.x << " , " << e.y << std::endl; }int Entity::x;int Entity::y;int main () { Entity e; e.x = 2 ; e.y = 3 ; print (e); }
ENUMS 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Log {public : enum Level { ERROR = 0 , WARNING, INFO }; const int LogLevelError = 0 ; const int LogLevelWarning = 1 ; const int LogLevelInfo = 2 ;private : int m_LogLevel = LogLevelInfo;public : void setLevel (int level) { m_LogLevel = level; } }int main () { Log log; std::cout << log.INFO << std::endl; }
output: 2 so we can see the value increasly itself.
Constructors 1 2 3 4 5 6 7 8 9 10 11 class Entity { int x, y; Entity (int _x, int _y) { x = _x; y = _y; } };int main () { Entity e (10 , 20 ) ; }
delete default construcator
1 2 3 4 5 6 7 8 class Log {public : Log () = delete ; }int main () { }
Destructors 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Entity { int x, y; Entity (int _x, int _y) { x = _x; y = _y; std::cout << "Created Entity!" << std::endl; } ~Entity (){ std::cout << "Destroyed Entity!" << std::endl; } };int main () { Entity e (10 , 20 ) ; e.~Entity (); }
Inheritance 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Player : Entity{} # Virtual Functions ```cppclass Player : public Entity {private : std::string m_Name;public : Player (const std::string &mName) : m_Name (mName) {} std::string getName () { return m_Name; } };int main () { Entity *e = new Entity (); std::cout << e->getName () << std::endl; Player *p = new Player ("john" ); std::cout << p->getName () << std::endl; }
output : Entity john 符合预期
添加 Entity* entity = p;
1 2 3 4 5 6 7 8 9 int main () { Entity *e = new Entity (); std::cout << e->getName () << std::endl; Player *p = new Player ("john" ); std::cout << p->getName () << std::endl; Entity* entity = p; std::cout << entity->getName () << std::endl; }
output: Entity john Entity
和java 类似,预期输出 john,但是实际输出 Entity.
再看一个方法的输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Entity {public : std::string getName () { return "Entity" ; } Entity () {} };class Player : public Entity {private : std::string m_Name;public : Player (const std::string &mName) : m_Name (mName) {} std::string getName () { return m_Name; } };void printName (Entity* entity) { std::cout << entity->getName () << std::endl; }int main () { Entity *e = new Entity (); printName (e); Player *p = new Player ("john" ); printName (p); }
output: Entity Entity 和预期也是不一致
virtual 新增
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Entity {public : virtual std::string getName () { return "Entity" ; } Entity () {} };class Player : public Entity {private : std::string m_Name;public : Player (const std::string &mName) : m_Name (mName) {} std::string getName () override { return m_Name; } };
新增virtual后 output: Entity john 和预期一致,类似于java多态。
Interfaces class 里只有virtual,说明这个class就是一个Interfaces
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Printable {public : virtual std::string getClassName () = 0 ; };class Entity : public Printable {public : virtual std::string getName () { return "Entity" ; } virtual std::string getClassName () override { return "Entity" ; } };class Player : public Entity {private : std::string m_Name;public : Player (const std::string &mName) : m_Name (mName) {} std::string getClassName () override { return "Player" ; } };void print (Printable *obj) { std::cout << obj->getClassName () << std::endl; }int main () { Entity *e = new Entity (); Player *p = new Player ("john" ); print (e); print (p); }
output : Entity Player
Array 1 2 3 4 5 6 7 8 9 10 11 12 13 int example[5 ];int * ptr = example;for (int i = 0 ; i < 5 ; ++i) { example[i] = 2 ; } example[2 ] = 5 ; *(ptr + 2 ) = 6 ;int * another = new int [5 ];for (int i = 0 ; i < 5 ; ++i) { another[i] = 2 ; }
Strings const
1 2 const char *name = "Cherno" ; name[2 ] = 'a' ;
1 2 3 4 5 6 7 8 9 10 void printString (std::string string) { string += "h" ; std::cout << string << std::endl; }int main () { std::string name = std::string ("john" ) + " hello" ; printString (name); std::cout << name << std::endl; }
output: john helloh john hello // name的h没有,数据没变化
reference 1 2 3 4 5 6 7 8 9 10 void printString (std::string &string) { string += "h" ; std::cout << string << std::endl; }int main () { std::string name = std::string ("john" ) + " hello" ; printString (name); std::cout << name << std::endl; }
output: john helloh john helloh 值发生的变化
const 不能修改指针指向内容的值 *a 但是指针a可以修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 int main () { const int MAX_AGE = 90 ; const int *a = new int ; int const * a = new int ; const int * a = new int ; int * const a = new int ; const int *const a = new int ; std::cout << "a point change before " << a << std::endl; a = (int *) &MAX_AGE; std::cout << *a << std::endl; std::cout << "a point change after " << a << std::endl; }
const int *a = new int; // 不能修改指针指向内容的值,指针的值可以修改
output: a point change before 0x600002620030 90 a point change after 0x16b886f5c
not pointer member 1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Entity {private : int m_X, m_Y;public : int getX () const { return m_X; } void setX (int x) { m_X = x; } };
pointer member 1 2 3 4 5 6 7 8 9 10 11 12 13 class Entity {private : int *m_X, *m_Y;public : const int *const getX () const { return m_X; } void setX (int x) { m_X = x; } };
上面两种情况,类似于java. get. set
Member Initializer Lists 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Entity {private : std::string m_Name;public : Entity () { m_Name = "UnKnown" ; } Entity (const std::string &name) { m_Name = name; } const std::string &getName () const { return m_Name; }; };int main () { Entity e0; std::cout<<e0.getName () <<std::endl; Entity e1 ("john" ) ; std::cout<<e1.getName () <<std::endl; }
output: UnKnown john
另一种写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Entity {private : std::string m_Name; int m_Score;public : Entity () : m_Name ("UnKnown" ), m_Score (0 ) {} Entity (const std::string &name) : m_Name (name) {} const std::string &getName () const { return m_Name; }; };int main () { Entity e0; std::cout << e0.getName () << std::endl; Entity e1 ("john" ) ; std::cout << e1.getName () << std::endl; }
可以看出这种写法更简单.而且还有另一个好处,下面来介绍.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Example {public : Example () { std::cout << "Created Example Entity!" << std::endl; } Example (int x) { std::cout << "Created Example Entity!" << x << "!" << std::endl; } };class Entity {private : std::string m_Name; Example m_Example; public : Entity () { m_Name = std::string ("UnKnown" ); m_Example = Example (8 ); } const std::string &getName () const { return m_Name; }; };int main () { Entity e0; }
output: Created Example Entity! Created Example Entity!8!
可以看到,创建了 2个对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Entity {private : std::string m_Name; Example m_Example;public : Entity () : m_Example (8 ) { m_Name = std::string ("UnKnown" ); } const std::string &getName () const { return m_Name; }; };int main () { Entity e0; }
output: Created Example Entity!8! 这样只创建了一个对象。
CREATE/INSTANTIATE OBJECTS stack 栈内存 会自动回收
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Entity {private : std::string m_Name;public : Entity () : m_Name ("UnKnown" ) {} Entity (const std::string &name) : m_Name (name) {} const std::string &getName () const { return m_Name; }; };int main () { Entity *e; { Entity entity ("john" ) ; e = &entity; std::cout << (*e).getName () << std::endl; } }
IDE不一样,视频中entity 为空的情况,不知道怎么模拟出来,
Heap allocated on the heap requires you to manually called delete
1 2 3 4 5 6 Entity *e; { Entity *entity = new Entity ("john" ); e = entity; std::cout << (*e).getName () << std::endl; }
The NEW Keyword new Entity(“john”);
The Arrow Operator 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class Entity {public : void print () const { std::cout << "hello" << std::endl; } };class ScopedPtr {private : Entity *m_Obj;public : ScopedPtr (Entity *entity) : m_Obj (entity) { } ~ScopedPtr () { delete m_Obj; } Entity* operator ->() { return m_Obj; } };int main () { ScopedPtr entity = new Entity (); entity->print (); }
chatgpt也说这个会编译错误 这一集视频,没看明白,包括上面的问题。