/
...
/
/
Chapter.2 Object Oriented
Search
Try Notion
Chapter.2 Object Oriented
Introduce
C Sharp 和 Java 就是面向对象的编程语言
实际上上面二者很难使用其他的编程模型
C++ 不同: 不约束写代码的方法
C 不能使用面向对象, 缺乏一些工具(概念)
Class Basic
引入
What’s Class? 将数据和功能组合在一起的方法
Why need Class?
想比较于C, 可能会出现大量无组织代码
函数传参要传递一大堆参数
CLass定义
💻Class Define
//in main.c class Player { int x,y; int speed; }; int main() { Player player1; std::cout << player1.x; }
Copy
C++
注意: Class定义后的 {...} 需要一个封号 ; 结尾( 函数定义就不需要 )
Class 可见性
引入
上述代码中, 实际上 cout 无法显示
这是因为我们需要设置Class的可见性
所有的内容默认为Private
可见性分类
Private: 只有类内函数才能访问这些变量
Pubic: 公开都可以访问
Class Include Funtion (Method)
我们把Class内部的函数称作方法
我们可以在Class定义的时候同时定义函数
💻Def Method in Class
class Player { public: int x,y; int speed; void Move(int xa, int ya) { x+=xa*speed; y+=ya*speed; } };
Copy
C++
Class外部函数往往也可以实现同样的功能, 只是让我们的代码更加简单了
当处理大代码, 保持代码整洁十分重要
Struct VS Class
区别:
只有一个很小的可见性区别即: Class 默认成员是Private, 这是二者技术(基本)上唯一的区别
C++中结构体, 也可以在结构体中定义函数
技术上区别不大, 但是使用上区别比较大
唯一C++有struct , 是为了和C保持兼容性
当然我们也可以通过不设立struct关键字, 而是用 #define class struct 来实现对C兼容, (可能还要修改下Public可见性)
使用上的区别来自于编程风格, 接下来我们介绍一些编程风格
Plain of Data Style
No Hierarchy: 不会在Struct 中使用继承
成员只有变量的时候使用 Struct
比如数学上的 Vector
How to Write a Class
💻Class Log Code
Class log { public: const int LogLevelError = 0; const int LogLevelWarning = 1; const int LogLevelMessage = 2; private: int m_LogLevel = LogLevelMessage ; public: void setLevel(int level) { m_LogLevel = level; } void setLevel(const char* message) { std::cout<< "[Warn]: " << message << std::endl; } }; int main() { Log log; Log.setLevel(LogLevelWarning); log.Warn("Hello!"); }
Copy
C++
Why Choose Log as Example
Log Class 可以根据需要十分简单(10Line) 或 非常的复杂(10KKLine)
比如打印用不同颜色 网络输出日志 日志错误等级(Error Warning Message)
对于调试 Debug 很重要, 所以值得花时间
代码讲解
一种编程方式 设计API的时候, 向研究它的使用方式: 即, 先编写main 函数里面的东西(Top to Down)
我们设计的API
初始化
设置错误等级
打印Warn到控制台
对于Private 成员, 希望能使用一个 m_ 前缀 这对大型项目的浏览有很大的帮助
可以有多个Public区域(Coding Style) Public Method在一个区域, Public Var在另一个区域, Public Static Var
默认我们设置LogLevelMessage
上面这个写法不好, 但是简单并且符合直觉, 接下来我们来改进这段代码
Static KeyWord
Static in Class Member
几乎在所有的语言中, 静态在一个类中意味着 “特定” 的东西
单一副本性质
这意味着在类的所有实例中这个变量只有一个实例
不管创建多少个Class 对象, static变量始终只有一个版本
如果某个实例改变了这个静态变量, 它会在所有实例中反映这个变化
Static Var 访问问题
如何使用在外部使用 Static var
但是我们依旧可以使用成员 . 来引用, 就好像是一个成员变量一样
比如声明类实体e1 Entity e1 , 那么 e1.xEntity::x 效果是一样的
就好像在命名空间 Entity 里面新建了两个变量, 而不属于class一样, 当然, 由于可见性问题比如Public ,实际上和命名空间不一样
Class 内部方法使用时候, 不需要加 :: 符号, 因为他们两个可看成在同一命名空间中
使用前的初始化
静态成员变量在类定义后不会被初始化(分配空间)
第一次使用的时候必须先声明
💻Exmaple
#include <stdio.h> class Point { public: static void output() { printf("%d\n", m_nPointCount); } private: static int m_nPointCount; }; void main() { Point pt; pt.output(); }
Copy
C++
Static Var静态函数使用问题
对于静态函数, 也是不需要创建类对象直接调用
和上面变量一致, 我们可以使用 Entity::method() 或者 e1.method()
普通类方法可以访问静态类变量和普通变量 , 但是 静态类方法不能访问普通类变量 可看成 静态类方法是共有的, 我们没法明确到底要访问哪个对象的成员
Static Class 很少使用, 只用于内部匿名类
🤔个人思考总结
静态 访问 非静态?
也即: 每个非静态方法总是获得当前类的一个实例作为隐藏参数(this 指针)
所以导致了: 静态方法只能访问静态变量 , 而无法访问实体变量
静态变量类外初始化?
就好比方法一样, 我们可以在类定义中声明我们要用到哪个函数, 具体的函数定义在外部实现
这里也是一样的, 我们在类内声明了静态变量, 而变量的初始化在类外实现
这样解释了: 为何上面的Example 中 Private Static var 在外面被 “使用” 的情况
💡菜鸟教程总结
静态数据成员
static var可以实现多个对象之间的数据共享, 它是类的所有对象的共享成员, 它在内存中只占一份空间, 如果改变它的值, 则各对象中这个数据成员的值都被改变.
static var是在程序开始运行时被分配空间, 到程序结束之后才释放, 只要类中指定了静态数据成员, 即使不定义对象, 也会为静态数据成员分配空间.
static var可以被初始化, 但是只能在类体外进行初始化, 若未对静态数据成员赋初值, 则编译器会自动为其初始化为0.
静态数据成员既可以通过对象名引用, 也可以通过类名引用.
静态成员函数
静态成员函数和静态数据成员一样, 他们都属于类的静态成员, 而不是对象成员.
非静态成员函数有this指针, 而静态成员函数没有this指针.
静态成员函数主要用来方位静态数据成员而不能访问非静态成员.
Static Other Usage
Static in HeadFile
引入: 在Chapter0 Before the Code 的 Head File一节中我们提到过Static一种用法
Static in HeadFile复习: 在HeadFile中用Static 修饰函数, 使得函数在每个C文件中,都有一份独立的定义
Local Scope Static
预先概念
Life Time(生存时间) and Scope(作用域)
Life Time: 在内存中存活的时间
Scope: 在哪里可见
这里的Local Static一般是指在 if{...}funtion(){...} 作用域内才能访问的Static
本质上和 Static in Class Member 没有区别, 仅仅是 Static in Class Member 可以被整个Class 访问, 也可被Class 外访问
生存时间二者是相同的, 都是永久
而函数的作用域不能被外部代码打开(我们可以通过指针将这个变量向外传出)
SingleTon Usage(Java 设计模式中的单例模式)
💻SingleTon With static in Class Member
Class SingleTon { private: static SingleTon* s_interface ; public: static SingleTon& Get(){return *s_interface; void hello(){} }; Singleton *Singleton::s_Instance = nullptr; int main() { Singleton::Get().hello() ; }
Copy
C++
💻SingleTon With Local Static
Class SingleTon { public: static SingleTon& Get() { static s_interface; return s_interface; } void hello(){} }; int main() { Singleton::Get().hello() ; }
Copy
C++
解析
创建Class的静态变量后
返回Class 静态变量的引用, 将其作为唯一的类实例使用
Enum