一、面向对象程序设计的基本特点
二、类成员的访问控制 public 类外(main()函数)不能访问 private 和 protected 类型,只能访问声明 public 的对外接口
private 类开头若不加访问权限,则默认为private类型
可被基类的成员函数访问
可被基类的友元函数访问
protected
可被基类的成员函数访问
可被基类的友元函数访问
派生类的成员函数可以访问 当前对象 基类的protected成员
举例如下:
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 class A { public : int c; private : int b; protected : int a; }; class B : public A{ void func () { c = 1 ; b = 1 ; a = 1 ; B f; f.a = 1 } } int main(){ B boo; A aoo; aoo.b = 1 ; aoo.a = 1 ; boo.b = 1 ; boo.a = 1 ; aoo.c = 1 ; boo.c = 1 ; return 0 ; }
三、构造函数/析构函数/复制构造函数 1. 构造函数: 构造函数的作用:在对象被创建时使用特定的值构造对象,将对象初始化为一个特定的初始状态。
1 2 3 4 5 6 7 class Complex { public : Complex(double r, double i = 0 ); }; Complex c1; Complex(2 ,1 );
可以有多个构造函数(参数类型/个数不同),但只能有一个析构函数 (可把delete语句放在析构函数中,先被构造的对象最后被析构掉)。
1 2 3 4 Test *pArray[3 ] = {new Test(4 ), new Test(1 ,2 )};
🚩 注 : 构造函数 不能被派生类继承
2. 析构函数:
析构函数和构造函数的调用顺序 遵循原则:先被构造的函数后被析构掉
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 Demo { int id; public : Demo(int i) { id = i; cout << "id=" << id << " Constructor" << endl ; } ~Demo() { cout << "id=" << id << " Destructor" << endl ; } }; Demo d1 (1 ) ; void Func () { static Demo d2 (2 ) ; Demo d3 (3 ) ; cout << "Func" << endl ; } int main () { Demo d4 (4 ) ; d4 = 6 ; cout << "main" << endl ; { Demo d5 (5 ) ; } Func(); cout << "main ends" << endl ; return 0 ; }
运行结果:
id=1 Constructor id=4 Constructor id=6 Constructor id=6 Destructor //d4 = 6临时对象的消亡 main id=5 Constructor id=5 Destructor id=2 Constructor id=3 Constructor Func id=3 Destructor main ends id=6 Destructor //Demo d4对象的消亡 id=2 Destructor id=1 Destructor
3. 复制构造函数: 复制构造函数是一种特殊的构造函数,其形参为本类的对象引用。作用是用一个已存在的对象 去初始化同类型的新对象。
复制构造函数被调用的三种情况:
用类的一个对象取初始化另一个对象时;
函数的返回值是类的对象,函数执行完成返回调用者时;
1 2 3 4 5 6 7 8 9 Point g () { Point a (1 ,2 ) ; return a; } int main () { Point b; b = g(); return 0 ; }
a是g( )的局部对象,离开g( )之后就消亡了,不可能再返回主函数后继续生存 。 所以这种情况下系统会创建一个临时无名对象 ,该临时对象的生存期只存在于函数调用所处的表达式中,即 b = g( )中。 执行语句 return a
,实际上是调用复制构造函数将a的值复制到临时对象中,函数g( )运行结束时对象a消亡,但临时对象会存在于表达式 b = g( ) 中,计算完这个表达式,临时对象也就自动消亡了。
函数的形参是类的对象,调用函数进行形参和实参结合时;
**举例如下:**
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 42 43 44 45 46 class Point { public : Point(int xx = 0 , int yy = 0 ) { x = xx; y = yy; } Point(const Point &p); void setX (int xx) { x = xx; } void setY (int yy) { y = yy; } int getX () const { return x; } int getY () const { return y; } private : int x, y; }; Point::Point(const Point &p) { x = p.x; y = p.y; cout << "Calling the copy constructor " << endl ; } void fun1 (Point p) { cout << p.getX() << endl ; } Point fun2 () { Point a (1 , 2 ) ; return a; } int main () { Point a (4 , 5 ) ; Point b (a) ; cout << b.getX() << endl ; fun1(b); b = fun2(); cout << b.getX() << endl ; return 0 ; }
拷贝构造函数和赋值运算符(=)有啥不同?
赋值运算符作用于一个已存在的对象;
拷贝构造函数会创建一个新对象。
四、类的组合 注意以下代码的构造函数和复制构造函数的调用顺序(原则:内嵌类先构造)
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 class Point { public : Point(int xx = 0 , int yy = 0 ) { x = xx; y = yy; cout <<"constructor of Point!" <<endl ; } Point(Point &p); int getX () { return x; } int getY () { return y; } private : int x, y; }; Point::Point(Point &p) { x = p.x; y = p.y; cout << "Calling the copy constructor of Point" << endl ; } class Line { public : Line(Point xp1, Point xp2); Line(Line &l); double getLen () { return len; } private : Point p1, p2; double len; }; Line::Line(Point xp1, Point xp2) : p2(xp2), p1(xp1) { cout << "Calling constructor of Line" << endl ; double x = static_cast <double >(p1.getX() - p2.getX()); double y = static_cast <double >(p1.getY() - p2.getY()); len = sqrt (x * x + y * y); } Line::Line(Line &l) : p1(l.p1), p2(l.p2) { cout << "Calling the copy constructor of Line" << endl ; len = l.len; } int main () { Point myp1(1, 1), myp2(4, 5); Line line (myp1, myp2) ; Line line2 (line ) ; cout << "The length of the line is: " ; cout << line .getLen() << endl ; cout << "The length of the line2 is: " ; cout << line2.getLen() << endl ; return 0 ; }
五、结构体和联合体 struct
union 例如:使用联合体保存成绩信息,并且输出。
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 42 43 44 45 46 47 48 49 50 51 52 53 #include <string> #include <iostream> using namespace std ;class ExamInfo { private : string name; enum { GRADE, PASS, PERCENTAGE } mode; union { char grade; bool pass; int percent; }; public : ExamInfo(string name, char grade) : name(name), mode(GRADE), grade(grade) {} ExamInfo(string name, bool pass) : name(name), mode(PASS), pass(pass) {} ExamInfo(string name, int percent) : name(name), mode(PERCENTAGE), percent(percent) {} void show () ; }; void ExamInfo::show(){ cout << name << ": " ; switch (mode) { case GRADE: cout << grade; break ; case PASS: cout << (pass ? "PASS" : "FAIL" ); break ; case PERCENTAGE: cout << percent; break ; } cout << endl ; } int main () { ExamInfo course1 ("English" , 'B' ) ; ExamInfo course2 ("Calculus" , true ) ; ExamInfo course3 ("C++ Programming" , 85 ) ; course1.show(); course2.show(); course3.show(); return 0 ; }
六、C++中的 . 操作符与 -> 操作符 1 2 3 4 5 6 7 8 9 10 11 12 13 14 struct Person { String name; String born; double money; }; Person A; Person *B = new Person; A.name = "Dr.nothing" ; B->name = "Dr.something" ; A.money = 300.0 ; (*B).money = 30 ;
若是使用到 ->
操作符则左边的变量必须是指针变量;
若是使用到 .
操作符那么左边的变量不能为指针,指针变量需要使用 *
操作符访问到该地址的内容