C++的部分知识复习,为了准备考试
C++·
C++面向对象·
1.类&对象·
基本操作·
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
| #include<iostream> #类定义 class People { private: double weight; int age; public: double getWeight(void); void setAge(int age2set); People(); People(int age2set,weight2set); };
People::People(){ weight=70; age=20; } People::People(int age2set,double weight2set){ age=age2set; weight=weight2set; }
double People::getWeight(){ return weight; } void People::set(int age2set){ age=age2set; }
People jack; People xiaoming(1,2);
|
析构函数·
在每次删除创建的对象时执行。类似构造函数,函数名与类名相同。只是函数名前要加一个~
。
这个函数不能有返回值和参数。有助于在跳出程序前释放资源。
1 2 3 4 5 6 7 8 9
| class Obj { public: ~Obj(); }; Obj::~Obj() { cout<<"Obj is being deleted" }
|
拷贝构造函数·
特殊的构造函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| classname (const classname &obj) { } class Obj { public: Obj(int len); Obj(const Obj &obj); private: int *p; }; Obj::Obj(int len) { p=new int; *p=len; } Obj::Obj(const Obj &obj) { p=new int; *p=*obj.p; } Obj obja(10); Obj objb = obja;
|
友元函数·
friend
关键字对函数进行声明即可,友元函数可以访问这个类的所有成员。如:
1 2 3 4 5 6 7 8 9 10 11
| class Obj { public: friend void printa(); friend class ClassB; private: int a; }; void printa(){ cout<<a; }
|
内联函数·
加上inline
关键字即可。一种用空间换时间的方式,在编译时会在每个调用这个函数的位置放置这个函数副本,所以空间开销大。
一般要使用最好行数较短,1-5行为宜,不要出现分支。
比如Max
,Min
等。
对象指针·
this指针·
是一个指向自身的指针,用this->变量/方法名
来使用。
普通对象指针用法与this一样。
静态成员·
static
关键词来定义。
创建第一个类对象时若无其他初始化语句,所有的静态数据会清0。之后所有新创建的同类都共享这个数据。
不能使用this指针。必须使用classname::fun()
的形式来调用。
2.C++继承·
基本形式是class A:access-specifier B;
同时,也可以多继承。如下代码所示
1 2 3 4
| class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,… { <派生类类体> };
|
修饰符是public/protected/private
,一般用public
,即父类的public/protected
成员都作为相同的权限被定义在子类中。其他两种则是将父类的public/protected
成员作为相应的权限被定义。同时,三种定义皆不能访问到父类的private
成员。
C++继承函数比较麻烦。
以下三种是不会继承的。其他符合权限限制的都可以访问。
- 基类的构造函数、析构函数和拷贝构造函数。
- 基类的重载运算符。
- 基类的友元函数。
这里实在太复杂,先简单罗列一下最常用的构造函数的继承使用说明。
构造原则如下(这里参考了这篇博客 https://blog.csdn.net/lzbzclz/article/details/105062566):
- 在类的继承的过程中,如果子类没有定义构造函数,程序就会自动调用父类的构造函数。
- 如果子类定义了构造函数且父类是无参的构造函数,那么创建类的时候会自动先调用父类的构造函数,再调用子类的构造函数。
- 如果子类定义了构造函数且没有显示调用父类中唯一的带参构造函数,程序会报错。
- 调用父类构造函数的时候得用初始化父类成员对象的方式。
举例如下
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
| class A{ public: A(int a); private: int a; }; A::A(int a){ this.a=a; } class B: public A{ public: B(int b); private: int b; }; B::B(int b){ this.b=b; } A a(10); B b(20);
class A{ public: A(int a); private: int a; }; A::A(int a){ this.a=a; } class B: public A{ public: B(int b); private: int b; }; B::B(int b):A(10){ this.b=b; } A a(10); B b(20);
|
3.重载运算符和重载函数·
函数和运算符都可以进行重载
调用时编译器通过使用的参数类型与定义中的进行比较,选择合适的,称为重载决策。
函数重载·
1 2 3 4 5 6 7 8 9 10 11 12
| class A { public: void print(){ cout<<"No Parameter!"; } void print(string a) { cout<< "p1:" << a; } } A a; A.print(); A.print1("a");
|
运算符重载·
关键字 operator
和其后要重载的运算符符号构成的,可以视为一个函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Box { public: Box operator+(const Box& b) { Box box; box.a = this->a+b->a; box.b = this->b+b->b; return box; } int a; int b; }
Box operator+(const Box& b1,const Box& b2) { Box box; box.a = b1->a+b2->a; box.b = b1->b+b2->b; return box; }
|
4.C++多态·
继承关联时会用到多态
调用成员函数时根据对象类型执行不同函数
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
| #include <iostream> using namespace std; class Shape { protected: int width, height; public: Shape( int a=0, int b=0) { width = a; height = b; } int area() { cout << "Parent class area :" <<endl; return 0; } }; class Rectangle: public Shape{ public: Rectangle( int a=0, int b=0):Shape(a, b) { } int area () { cout << "Rectangle class area :" <<endl; return (width * height); } }; class Triangle: public Shape{ public: Triangle( int a=0, int b=0):Shape(a, b) { } int area () { cout << "Triangle class area :" <<endl; return (width * height / 2); } };
int main( ) { Shape *shape; Rectangle rec(10,7); Triangle tri(10,5); shape = &rec; shape->area(); shape = &tri; shape->area(); return 0; }
|
上面代码中,由于基类中实定义了函数,后面两处都输出 Parent class area:
- 这里也被称为 静态多态/静态链接,在程序执行前就已经将
area
函数定死了。
只需要在基类的函数定义前加关键字virtual
,进行虚定义,后面输出的就是正常的各自的输出。
这时就是根据不同的指针地址的位置的 area
函数来执行了。
虚函数·
1 2 3 4 5 6
| virtual int area() { cout<<"Hello"; }
virtual int area() = 0;
|
5.C++数据抽象与封装·
-
数据抽象:仅向用户暴露接口而隐藏具体实现细节的机制。
-
数据封装:把数据和操作数据的函数捆绑在一起的机制。
-
数据成员和外界不需要的类内方法函数用private
,外部接口方法用public
6.C++ 接口(抽象类)·
接口:类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类
这个和Java
中的接口是一样的,直接用接口去定义一个实例会报错,需要具体实现
比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Box { public: virtual double getVolume() = 0; void setLength(double length) { this->length = length; } private: double length; double breadth; double height; }; class BoxChild:public Box { public: double getVolume(){ return this->length; } }
|
课程思维导图·