类 概念 类其实类似结构体,就是里面可以放函数,然后增添了很多特性
还有就是
struct 默认public
class默认private
类成员函数 放在类里的函数
在类中声明后,可以在类中定义,也可以在类外定义
1 2 3 4 5 6 7 8 9 10 11 12 class Box { public : double length; double breadth; double height; double getVolume (void ) { return length * breadth * height; } };
1 2 3 4 double Box::getVolume (void ) { return length * breadth * height; }
类访问修饰符 public:没什么好说的
private::在类外无法被直接引用
protected:同private,但在派生类的类中可以引用
友元函数 友元函数
友元类
构造函数 struct 默认public
class默认private
static就是类的变量或方法,不用实例化
构造函数
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 #include <iostream> using namespace ::std;class Student {private : string m_name; int m_age; float m_score; public : void show () ; Student (string name, int age, float score); Student (); }; void Student::show () { cout << m_name << "年龄" << m_age << "成绩" << m_score; } Student::Student () { cout << m_name << "年龄" << m_age << "成绩" << m_score; } Student::Student (string name, int age, float score) { m_name = name; m_age = age; m_score = score; } int main () { Student student ("haidragon" , 25 , 10.1 ) ; student.show (); Student* pstudent = new Student ("haidragon" , 25 , 10.1 ); pstudent->show (); delete (pstudent); return 0 ; }
1.构造函数 作用:对象所在的内存空间做初始化 、给对象赋资源 2.析构函数 作用:释放对象所占的其他资源。 3.拷贝构造函数 作用:拿一个已存在的对象来生成相同类型的新对象. 4.赋值运算符的重载函数 作用:拿一个已存在的对象给相同类型的已存在对象赋值. 5.一般对象取地址函数. 6.常对象取地址函数.
C++11以后增加了右值引用的概念,同时增加了移动构造函数、和移动赋值函数。 7.移动构造函数。 8.移动赋值函数。
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 #include <iostream> using namespace std;class TestCls { public : int a; int *p; public : TestCls () { std::cout<<"调用无参构造函数" <<std::endl; p = new int ; } TestCls (const TestCls & a){ std::cout<<"调用拷贝构造函数" <<std::endl; } TestCls operator = (const TestCls & a){ std::cout<<"调用赋值构造函数" <<std::endl; } TestCls* operator & (){ std::cout<<"调用取地址构造函数" <<std::endl; } const TestCls* operator &() const { std::cout<<"const修饰的取地址操作符重载" <<std::endl; } ~TestCls () { delete p; std::cout<<"调用析构函数" <<std::endl; } }; int main (void ) { TestCls t1; TestCls t2 (t1) ; TestCls t3 = t2; t3 = t1; TestCls* t4=&t3; const TestCls* t5=t4; const TestCls* t6=&t3; const TestCls t7; const TestCls* t8=&t7; 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 #include <iostream> using namespace ::std;void test1 (int i, int j) { int temp = i; i = j; j = temp; } void test2 (int * i, int * j) { int temp = *i; *i = *j; *j = temp; } void test3 (int & i, int & j) { int temp = i; i = j; j = temp; } int main () { int i = 1 ; int j = 2 ; printf ("%d,%d\n" , i, j); i = 1 ; j = 2 ; test1 (i, j); printf ("%d,%d\n" , i, j); i = 1 ; j = 2 ; test2 (&i, &j); printf ("%d,%d\n" , i, j); i = 1 ; j = 2 ; test3 (i, j); printf ("%d,%d\n" , i, j); return 0 ; } 1 ,2 1 ,2 2 ,1 2 ,1
1、两者的定义和性质不同 指针是一个变量,存储的是一个地址,指向内存的一个存储单元;
引用是原变量的一个别名,跟原来的变量实质上是同一个东西。
int a = 996; int *p = &a; // p是指针, &在此是求地址运算 int &r = a; // r是引用, &在此起标识作用
上面定义了一个整型变量 a,p 是一个指针变量,p 的值是变量 a 的地址;
而引用 r,是 a 的一个别名,在内存中 r 和 a 占有同一个存储单元。
2、指针可以有多级,引用只能是一级 int **p; // 合法 int &&a; // 不合法
3、指针可以在定义的时候不初始化,引用必须在定义的时候初始化 int *p; // 合法 int &r; // 不合法 int a = 996; int &r = a; // 合法
4、指针可以指向NULL,引用不可以为NULL int *p = NULL; // 合法 int &r = NULL; // 不合法 5、修改引用就直接修改被引用对象 int a = 996; int *p = &a; // 初始化, p 是 a 的地址 int &r = a; // 初始化, r 是 a 的引用
int b = 885; p = &b; // 合法, p 更改为 b 的地址 r = b; 6、sizeof 的运算结果不同 int a = 996; int *p = &a; int &r = a;
cout << sizeof(p); // 返回 int* 类型的大小 cout << sizeof(r); // 返回 int 类型的大小
继承 访问public protected private 同一个类yes yes yes 派生类 yes yes no 外部的类yes no no
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> using namespace std; // 基类 class Shape { public: void setWidth(int w) { width = w; } void setHeight(int h) { height = h; } protected: int width; int height; }; // 派生类 class Rectangle: public Shape { public: int getArea() { return (width * height); } }; int main(void) { Rectangle Rect; Rect.setWidth(5); Rect.setHeight(7); // 输出对象的面积 cout << "Total area: " << Rect.getArea() << endl; return 0; }
继承类型 继承类型 当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种类型。继承类型是通过上面讲解的访问修饰符 access-specifier 来指定的。
我们几乎不使用 protected 或 private 继承,通常使用 public 继承。当使用不同类型的继承时,遵循以下几个规则:
公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。 保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。 私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。
多继承
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 #include <iostream> using namespace std; // 基类 Shape class Shape { public: void setWidth(int w) { width = w; } void setHeight(int h) { height = h; } protected: int width; int height; }; // 基类 PaintCost class PaintCost { public: int getCost(int area) { return area * 70; } }; // 派生类 class Rectangle: public Shape, public PaintCost { public: int getArea() { return (width * height); } }; int main(void) { Rectangle Rect; int area; Rect.setWidth(5); Rect.setHeight(7); area = Rect.getArea(); // 输出对象的面积 cout << "Total area: " << Rect.getArea() << endl; // 输出总花费 cout << "Total paint cost: $" << Rect.getCost(area) << 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 #include <iostream> class Shape{ public: void setWidth(int w){ width=w; } void setHeight(int h){ height=h; } public: int width; int height; }; class PaintCost { public: virtual int getCost(int area) { return area * 70; } }; class Rectangle{ public: Shape shape; public: int getArea(){ return shape.width*shape.height; } }; class Rectangle2:public Shape,public PaintCost{ //public: Shape shape; public: int getArea(){ return width*height; } public: int getCost(int area) { return area * 30; } }; int main(){ Rectangle Rect; Rect.shape.setHeight(3); Rect.shape.setWidth(3); int i=Rect.getArea(); Rectangle2 Rect2; Rect2.setWidth(4); Rect2.setHeight(5); i=Rect2.getCost(4); printf("%d\n",i); PaintCost* pPaintCost=&Rect2; i=pPaintCost->getCost(4); printf("%d\n",i); return 0; }
运算符重载
命名空间