- 重名问题与命名规范
-
this是可以省略的
int Add() { return x+y; } printf("Sum:%d \n",Add());
-
重名问题:就近原则
在成员函数里:当局部变量与成员变量重名时,该变量指向的是局部变量。int x = 10; // 全局变量x void Sum(int x, int y) { printf("global"); return x + y; } class Object { public: int x; // 成员变量x void Sum(int x, int y) { return x + y; } void Test(int x) { printf("x = %d\n",x + this->x); // 最近的:函数内定义的x } }; int main() { Object obj; obj.x = 1; obj.Test(2); // 返回结果为3 return 0; }
总结:使用x对应的局部变量x,使用this->使用成员变量x,使用::x访问全局变量x
同理,函数也是就近原则,使用全局函数::Sum
- 命名规范
类名-每个单词的首字母大写-大驼峰
成员函数-每个单词的首字母大写-大驼峰-动词或者动宾形式
eg.
Open
Close
Add
Remove
SendMessage
RecvMessage
- 函数名的特点:
- 通常是成对出现的
- 常用函数名有限,顾名思义
- 成员变量-消协开头,第二个单词开头大写-小驼峰-通常加上前缀m_
eg.
m_number
m_server
m_port
m_buffer
m_maxsize
- 类的封装
-
所谓封装,是指把细节隐藏在内部,只把函数接口暴露在外
-
封装的是什么?数据,逻辑
-
C/struct,struct内部可以自由访问,无法完全地实现封装;引入class和访问修饰符后,可以实现完全的封装。
-
明确:什么想让用户看到,什么不想让用户看到:
-
把所有的成员变量设为private
-
添加函数接口,供外部操作该对象
-
getter,setter,及其他功能接口
-
eg. 圆 直角坐标系中的一个圆Circle,有圆心坐标(x, y),半径radius
-
-
-
成员变量:成员函数和成员变量在类的内部没有前后顺序之分
- 完全公开,就用public
- 完全不允许访问,就用private
- 只读:getter,该成员是可以读的
- 只写:setter,该成员是可以写的
class Circle { public: int GetX() { return m_x; } int GetY() { return m_y; } void MoveTO(int x, int y) { m_x = x; m_y = y; } void SetRadius(int radius) { m_radius = r; } double area() { return 3.14 * m_radius * m_radius; } // 1表示在里面 int Contain(double x, double y) { if(x^2 + y^2 < m_radius^2) { return 1; } return 0; } private: int m_x; int m_y; int m_radius; }; int main() { Circle obj; obj.SetRadius(2); obj.MoveTo(0,0) int area = obj.Area(); if(obj.Contain(1.2,1.3)) { printf("yes,in it\n"); } return 0; } ```
-
联系学生struct datestore,用class实现
class DataStore { public: void DCreate() {} void Destroy() {} void Add(const Student* data) void Print() {} private: Student m_head; }
-
小结:封装
-
用访问控制符可以实现类的封装;
-
很明确告诉用户,哪些可以调用,那些不可以调用;
public:
private:
-
- class的头文件与源文件分离
-
把class的成员函数的定义写在class之外,即class的大括号外面
class Object { public: int x; void Test(); // (1) 成员函数的声明 } void Object::Test() // (2) 成员函数写在外边,加上类名限定 { }
-
小结:class的分离式写法
-
成员变量:还是写在类里面;
-
成员函数:在类里保留其函数声明,而函数的定义写在类体之外;
-
写在外面的时候,要加上类名限定(Object:😃
其中,::可以理解为是表示范围的符号
-
-
按照一贯的原则:类型定义写在头文件里,函数实现写在源文件里
//Object.h// #ifndef _OBJECT_H #define _OBJECT_H // 防止重复包含,头文件保护 class Object { public: int x; void Test(); }; void Object::Test() { printf("x is %d \n", x); // 可以省略this-> } #endif // #include <stdio/h> #include "Object.h" int main() { Objecet obj; obj.x = 1111; obj.Test(); return 0; }
-
学生节点举例
//DataStore.h #ifndef _DATA_STORE_H #define _DATA_STORE_H struct Student { int id; char name[32]; Student *next; } class DataStore { public: void Create(); void Destroy(); void Add(const Student* data); void Print(); private: Student m_head; } #endif ///DataStore.cpp/// #include "DataStore.h" void DataStore::Create(); { } void DataStore::Destroy(); { } void DataStore::Add(const Student* data); { } void DataStore::Print(); { }
-
注意:不一定要把所有函数定义都拿出来,可以只拿一部分出来。
- 如果写在类体里面,编译器按照inline的规则编译它
- 类体之外,则是普通的函数
-
在类体中,成员函数与成员变量的排列顺序是自由的。