类:定义是以关键字 class 开头,后跟类的名称。类的主体是包含在一对花括号中。类定义后必须跟着一个分号或一个声明列表。例如:
1 class student 2 { 3 public: 4 int a = 5; 5 void math(){}; 6 7 private: 8 double b = 2.5; 9 int chines(){ return 0}; 10 }
定义类的对象: student std; 访问类的成员 std.math;
类成员函数:类的成员函数是指那些把定义和原型写在类定义内部的函数。类成员函数是类的一个成员,它可以操作类的任意对象,可以访问对象中的所有成员。当然也可以在类的外部使用范围解析运算符 :: 定义该函数。::前面是类名,后面是所要定义的函数。如果::前面不加类名,表示全局数据或全局函数(即非成员函数)。举个栗子:
1 #include <iostream> 2 using namespace std; 3 4 class student 5 { 6 public: 7 void stdinfo(){}; //这个函数和下面的全局函数stdinfo不是一个 8 void stdsen(); 9 void stdex() //类里面定义函数 10 { 11 cout << "I am a good student!" << endl; 12 } 13 }; 14 15 void stdinfo() 16 { 17 cout << "this is xiaodang !" << endl; 18 } 19 20 void student::stdsen() //类外面定义函数 21 { 22 cout << "I study math!" <<endl; 23 } 24 25 int main() 26 { 27 student std; 28 ::stdinfo(); 29 std.stdsen(); 30 std.stdex(); 31 return 0; 32 }
结果为:
this is xiaodang ! I study math! I am a good student!
类访问修饰符: 类的访问修饰符有三种是:public、private、protected,其中private和protected修饰的成员都是表示只能在类里面被访问(友元函数可以访问),他们的唯一的区别就是protected修饰的成员可以被派生类访问。而public可以被外部访问。举个栗子:
1 #include <iostream> 2 using namespace std; 3 4 class student 5 { 6 private: 7 int gh = 5; 8 void exOne() { cout << "This is a private" << endl; } 9 public: 10 void exTwo() { cout << "This is a public" << gh << endl; } //gh可以被访问,因为他是类内部成员 11 protected: 12 void exThree() { cout << "This is a protected" << endl; } 13 }; 14 15 class temp :public student 16 { 17 void exfour() { cout << "默认情况下的是private" << endl; } 18 }; 19 20 class temp_ex :protected student 21 { 22 }; 23 24 int main() 25 { 26 student std; 27 //std.exOne(); //protected不可访问 28 std.exTwo(); 29 //std.exThree(); //protected不可访问 30 31 temp te; 32 te.exTwo(); //可以访问,因为通过修饰词public继承下来的类他的成员的属性还是跟原来的一样。 33 //te.exfour(); //不可访问,因为类中默认情况下是private; 34 35 temp_ex ex; 36 //ex.exTwo(); //不可访问,因为通过修饰词proteed继承下来的类他的成员属相会降级,详细看下面的解释 37 return 0; 38 }
结果为: This is a public5 This is a public5
有public, protected, private三种继承方式,它们相应地改变了基类成员的访问属性。
-
1.public 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:public, protected, private
-
2.protected 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:protected, protected, private
-
3.private 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:private, private, private
但无论哪种继承方式,上面两点都没有改变:
-
1.private 成员只能被本类成员(类内)和友元访问,不能被派生类访问;
-
2.protected 成员可以被派生类访问。
构造函数 & 析构函数:这里我们只是简单的讲一下,具体后来在好好分析下这个。类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。举个栗子:
1 #include <iostream> 2 3 using namespace std; 4 5 class Line 6 { 7 public: 8 void setLength( double len ); 9 double getLength( void ); 10 Line(); // 这是构造函数 11 12 private: 13 double length; 14 }; 15 16 // 成员函数定义,包括构造函数 17 Line::Line(void) 18 { 19 cout << "Object is being created" << endl; 20 } 21 22 void Line::setLength( double len ) 23 { 24 length = len; 25 } 26 27 double Line::getLength( void ) 28 { 29 return length; 30 } 31 // 程序的主函数 32 int main( ) 33 { 34 Line line; 35 36 // 设置长度 37 line.setLength(6.0); 38 cout << "Length of line : " << line.getLength() <<endl; 39 40 Line line_temp; 41 line_temp.setLength(6.0); 42 43 return 0; 44 }
结果为:
Object is being created Length of line : 6 Object is being created
类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。举个最简单的栗子:
1 #include <iostream> 2 using namespace std; 3 4 class MyClass 5 { 6 public: 7 MyClass(); 8 ~MyClass(); 9 10 private: 11 12 }; 13 14 MyClass::MyClass() 15 { 16 cout << "这是一个构造函数,用来初始化" << endl; 17 } 18 19 MyClass::~MyClass() 20 { 21 cout << "这是一个析构函数,用来释放资源" << endl; 22 } 23 24 int main() 25 { 26 MyClass cal; 27 }
结果为: 这是一个构造函数,用来初始化 这是一个析构函数,用来释放资源
友元函数:类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend。另外注意因为友元函数没有this指针,则参数要有三种情况:
- 要访问非static成员时,需要对象做参数;
- 要访问static成员或全局变量时,则不需要对象做参数;
- 如果做参数的对象是全局对象,则不需要对象做参数。可以直接调用友元函数,不需要通过对象或指针
1 #include <iostream> 2 using namespace std; 3 4 class MyClass 5 { 6 public: 7 void ex(string temp) 8 { 9 if (temp == "IT") 10 { 11 cout << "恭喜你成功进入计算机学院系统!" << endl; 12 } 13 } 14 private: 15 int ID = 24615; 16 string Name = "xido"; 17 friend void Getsen(MyClass myclass); //友元函数 18 }; 19 20 void Getsen(MyClass myclass) //友元函数 21 { 22 if (myclass.ID == 24615) //因为是友元函数所以可以访问私有的成员变量 23 { 24 cout << "欢迎您登陆!" << endl; 25 } 26 } 27 28 int main() 29 { 30 string temp = "IT"; 31 MyClass yc; 32 Getsen(yc); 33 yc.ex(temp); 34 return 0; 35 }
结果为: 欢迎您登陆! 恭喜你成功进入计算机学院系统!
内联函数:C++ 内联函数是通常与类一起使用。如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则将会继续使用旧的函数。如果想把一个函数定义为内联函数,则需要在函数名前面放置关键字 inline,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略 inline 限定符。在类定义中的定义的函数都是内联函数,即使没有使用 inline 说明符。引入内联函数的目的是为了解决程序中函数调用的效率问题,这么说吧,程序在编译器编译的时候,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体进行替换,而对于其他的函数,都是在运行时候才被替代。这其实就是个空间代价换时间的节省。所以内联函数一般都是1-5行的小函数。使用内联函数时要神:
- 1.在内联函数内不允许使用循环语句和开关语句;
- 2.内联函数的定义必须出现在内联函数第一次调用之前;
- 3.类结构中所在的类说明内部定义的函数是内联函数。
this指针:在 C++ 中,每一个对象都能通过 this 指针来访问自己的地址。this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。友元函数没有 this 指针,因为友元不是类的成员。只有成员函数才有 this 指针。
1 #include <iostream> 2 using namespace std; 3 4 class student 5 { 6 public: 7 void Getstdinfo() 8 { 9 cout << "The first std`s id :" << stdinfo1 << endl; 10 cout << "The second std`s id :" << stdinfo2 << endl; 11 } 12 13 void Getstdex() 14 { 15 this->Getstdinfo(); //使用this指针 16 cout << "The first ex`s id :" << stdex1 << endl; 17 cout << "The second ex`s id :" << stdex2 << endl; 18 } 19 20 private: 21 int stdinfo1 = 24615; 22 double stdex1 = 95.5; 23 24 int stdinfo2 = 24616; 25 double stdex2 = 86.6; 26 }; 27 28 int main() 29 { 30 student std; 31 std.Getstdex(); 32 }
结果为:
The first std`s id :24615 The second std`s id :24616 The first ex`s id :95.5 The second ex`s id :86.6
指向类的指针:一个指向 C++ 类的指针与指向结构的指针类似,访问指向类的指针的成员,需要使用成员访问运算符 ->,就像访问指向结构的指针一样。与所有的指针一样,您必须在使用指针之前,对指针进行初始化。this就是一个指向类的指针。
1 #include <iostream> 2 using namespace std; 3 4 class MyClass 5 { 6 public: 7 MyClass(int a,int b); 8 ~MyClass(); 9 10 int sum() 11 { 12 return sum1 + sum2; 13 } 14 15 private: 16 int sum1 = 0; 17 int sum2 = 0; 18 }; 19 20 MyClass::MyClass(int a, int b) 21 { 22 sum1 = a; 23 sum2 = b; 24 } 25 MyClass::~MyClass() 26 { 27 } 28 29 int main() 30 { 31 MyClass my(4, 5); 32 MyClass *p; 33 p = &my; 34 cout << p->sum() << endl; //利用指向类的指针去访问类成员函数 35 }
结果为:9
类的静态成员:我们可以用static修饰词来定义类成员为静态的,当我们把类成员定义成了静态时,无论创建了多少个对象,静态成员的副本只有一个。静态成员在类的所有对象中是共享的。类中特殊成员变量的初始化问题:
- 常量变量:必须通过构造函数参数列表进行初始化。
- 引用变量:必须通过构造函数参数列表进行初始化。
- 普通静态变量:要在类外通过"::"初始化。
- 静态整型常量:可以直接在定义的时候初始化。
- 静态非整型常量:不能直接在定义的时候初始化。要在类外通过"::"初始化。
类的静态成员(变量和方法)属于类本身,在类加载的时候就会分配内存,可以通过类名直接去访问(::);非静态成员(变量和方法)属于类的对象,所以只有在类的对象产生(创建类的实例)时才会分配内存,然后通过类的对象(实例)去访问(.或者->)。
1 #include <iostream> 2 using namespace std; 3 4 class student 5 { 6 public: 7 static int i; //静态变量 8 int getSum(string Name) 9 { 10 if (name == Name){return math + chiness + english;} 11 else{return -1;} 12 } 13 student(); 14 15 private: 16 string name; 17 int math; 18 int chiness; 19 int english; 20 }; 21 int student::i = 0; //普通静态变量:要在类外通过"::"初始化。 22 student::student() //用构造函数初始化变量 23 { 24 name = "jim"; 25 math = 95; 26 chiness = 93; 27 english = 98; 28 i++; 29 } 30 31 int main() 32 { 33 student std; 34 cout << "总的成绩为:" << std.getSum("jim")<< endl 35 << "i = " << student::i << endl; 36 cout << "总的成绩为:" << std.getSum("tom") << endl 37 << "i = " << student::i << endl;40 return 0; 41 }
结果为: 总的成绩为:286 i = 1 总的成绩为:-1 i = 1
静态成员函数:如果把函数成员声明为静态的,就可以把函数与类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。静态成员函数与普通成员函数的区别:
- 静态成员函数只能访问静态数据、静态成员函数和类外其他函数。
- 静态成员函数没有this指针。
1 #include <iostream> 2 using namespace std; 3 4 class student 5 { 6 public: 7 static int i; //静态变量 8 int getSum(string Name) 9 { 10 if (name == Name){return math + chiness + english;} 11 else{return -1;} 12 } 13 student(); 14 static int retsta() 15 { return i; } 16 private: 17 string name; 18 int math; 19 int chiness; 20 int english; 21 }; 22 int student::i = 0; //普通静态变量:要在类外通过"::"初始化。 23 student::student() //用构造函数初始化变量 24 { 25 name = "jim"; 26 math = 95; 27 chiness = 93; 28 english = 98; 29 i++; 30 } 31 32 int main() 33 { 34 cout /*<< "总的成绩为:" << student::getSum("tom") << endl*/ //没有实例化对象导致无法调用普通成员函数 35 << "i = " << student::i << endl //静态变量可以直接调用,因为在类加载的时候,就已经分配内存了 36 << "静态函数返回的变量 = " << student::retsta() << endl; //和静态变量相似,来处理静态变量 37 student std; 38 cout << "总的成绩为:" << std.getSum("jim")<< endl 39 << "i = " << student::i << endl; 40 student dnet; 41 cout << "总的成绩为:" << dnet.getSum("jim") << endl 42 << "i = " << student::i << endl; 43 return 0; 44 }
结果为:
i = 0 静态函数返回的变量 = 0 总的成绩为:286 i = 1 总的成绩为:286 i = 2