C++开发基础整理
来源:互联网 发布:axure mac 团队协作 编辑:程序博客网 时间:2024/05/29 05:02
c++文件会以.cpp为后缀名 例如:abc.cpp #include<iostream> c++的头文件 一个例子: #include<iostream> using namespace std; //名字空间 int main(){ int a=100; int b=200; cout<<"hello"<<endl; //endl代表换行 输出 cout<<"a="<<a<<";"<<"b="<<b<<endl; cin>>a; //输入 cout<<"a="<<a<<endl; return 0; } g++ abc.cpp 进行编译 与c比较 c++中含有 string 类型 C++中有类的概念 class stu{ private: //定义下面的变量是私有变量只能使用类中的函数操作,私有变量只能在本类中使用,可以定义一个公有的函数进行调用操作 //修饰关键字后面需要加冒号:默认下面的都被此关键字修饰 直到遇到下一个关键字 int id; string name; int math; public: void set(int id2,string name2,int math2){ id=id1; name=name1; if(math2>=0){ math=math2; } } }; c 数据:结构体 逻辑:函数 c++ 类,对象,封装(数据安全性),继承(代码复用性),多态(代码易用性) 类 定义 class student(类名){ //类名首字母可以小写 属性; //变量 方法; //函数 }; //这里要加分号 student stu1; 定义一个对象 类名首字母可以小写 类就是按一定规则归类,是看不见,模不到的 可以看作一种新的数据类型 类在代码区 对象就是类的一个实体 一个例子: ..................................................................................... #include<iostream> using namespace std; class student{ private: int id; string name; public: void set(int id1,string name1){ id=id1; name=name1; } int getId(){ return id; } string getName(){ return name; } void print(); //需要声明一下 }; void student::print(){ //::域运算符, 表明print是属于student类的 count<<"name="<<name<<endl; } int main(){ student stu1; stu1.set(101,"huahua"); cout<<"id="<<stu1.getId()<<endl; cout<<"name="<<stu1.getName()<<endl; return 0; } .......................................................................................... this指针 谁调用函数 this指的就是谁的首地址 我们在成员函数中可以通过下面的语句打印出来this所指向的地址 cout<<"&this="<<this<<endl; inline内联函数 一个函数的声明和实现都写到类里面 此函数默认就是内联函数 例如上面的:set() print()就不是内联的成员函数,如果在前面加inline void student::printf(){} 就成为内联函数 private: 变量成员只能在本类中访问 protected: public: 任何地方都可以调用 构造函数 类生成的对象初始化,与类名相同,每次生成对象时自动调用 不能写返回值和return,可以带参数,是对象产生时自动执行的第一个函数 student(int id1,string name1){ id=id1; name=name1; } 当建立对象时,为对象所在内存做初始化操作,为了数据的安全性考虑 student stu1(12,"花花"); 构造函数可以写多个,体现了函数重载 函数重载:函数名相同,参数表不同(个数不同或参数类型不同),仅仅是返回值类型不同的不能构成重载,重载函数必须作用域相同 重载是多态的一种表现 必需传递参数 c语言靠函数名区分函数 c++靠函数名和参数列表区分函数 如果未写构造函数,系统自动默认无参构造函数,如果写了一个不管是什么样的,系统默认构造函数失效 如果提供的构造函数为有参构造函数,如果该构造函数所有的参数都有默认值,那么该构造函数为默认构造函数(这个时候就不能在写默认构造函数了),调用的时候可以不提供参数 void print(int a=100;int b=200){ printf("这样就是参数默认值"); } 这样调上面的函数,如果不传参数也会执行,默认传递了参数并使用默认值,这在C语言中是不行的 如果函数参数列表中即含有有默认值的参数,也含有没有默认值的参数,没有默认值的参数需要放在前面, void print(int a,int aa,int b=100,int c=200){ } 这样调用的时候 print(188,33); 就把参数传递给了没有默认值的参数 这在C语言中也是不行的 析构函数 对象释放前调的最后一个函数, 用于释放对象所占资源,处理善后工作 在析构函数中再自己写代码关闭资源 析构函数的名字由 ~ 加类名构成,一个类最多只有一个析构函数,不能重载,无参数,无返回值,也不能写return语句,与类名相同 析构顺序 先构造的对象后析构 动态的创建对象 new :相当于malloc() new 会分配堆区的内存 malloc分配单元以字节为单位,new分配单元以类型为单位 例如: int *p=NULL; p=new int; p指向一个整型指针,相当于给p分配了4个字节的内存,此时p已经有了指向,它此时已经控制了4个字节 *p=100; 把100存入p控制的内存中 动态的分配数组 int *px=NULL; px=new int[10]; //这样分配都会分配堆区的内存 释放内存 delete 释放自定义类型对象所占内存 只是释放指针指向的内存,指针还存在,相当于free() delete p; delete []px; 这里释放指向数组的指针要前面加[] 动态的创建和释放对象 new 创建对象 1.分内存 2.调用构造函数初始化 3.返回内存首地址 malloc 1.分内存 2.返回内存首地址 不能进行初始化 student *p=NULL; p=new student; //这样就生成了一个对象 可以调用有参构造函数 并传参 p=new student(1,"haha"); p->print(); delete p; //1.调用自定义的析构函数,处理相关工作 2.释放p指向的内存 创建对象数组 student *px=NULL; px=new student[3]; //必须调用默认构造函数,不能传参 px[0].print(); px[1].print(); px[2].print(); delete []px; 构造函数初始化列表 只有构造函数才有初始化列表 类中的常量 必须在构造函数初始化列表中初始化 下面是一个例子: #include<iostream> using namespace std; class A{ public: int a; const int b; //常量必须在初始化列表中初始化 A():b(0),a(0){ //无参的构造函数, 构造函数名后加:然后是变量名加() 里面写上值 } A(int a1,int b1):a(a1),b(b1){ //如果定义对象是传参可以使用这种方法 ,会动态的赋值 } void print(){ cout<<"a="<<a<<"\n"<<"b="<<b<<endl; } }; int main(){ A n; A m(100,200); n.print(); m.print(); return 0; } 复合 一个类的对象是另一个类的成员,就是复合 复合一个例子: #include <iostream> using namespace std; class A { private: int x; int y; public: A() { x=0; y=0; cout<<"A无参构造函数"<<endl; } A(int x1,int y1) { x=x1; y=y1; cout<<"A有参构造函数"<<endl; } ~A() { cout<<"A析构函数"<<endl; } void set(int x1,int y1) { x=x1; y=y1; } void print_A() { cout<<"x="<<x<<endl; cout<<"y="<<y<<endl; } }; class B { public: A a; int m; int n; B() { m=0; n=0; cout<<"B无参构造函数"<<endl; } B(int x1,int y1,int m1,int n1):a(x1,y1) //可以在这里给a带去初始化的值 { m=m1; n=n1; cout<<"B有参构造函数"<<endl; } ~B() { cout<<"B析构函数"<<endl; } void set(int x1,int y1,int m1,int n1) //也可以通过这里传参 { a.set(x1,y1); m=m1; n=n1; } void print_B() { a.print_A(); cout<<"m="<<m<<endl; cout<<"n="<<n<<endl; } }; int main() { B b1(100,200,300,400); b1.print_B(); b1.a.print_A(); b1.set(1,2,3,4); b1.print_B(); return 0; } const对象和const成员函数 const A a; 这就是一个const对象 const A a(2,3); 可以这样初始化,但是不能更改 A a1; A a2; a=a1; 是错误的,而且a中的成员变量也不能改变 a.print(); 也是错误的,不能调用A类的普通函数 但是 void print()const{ } 可以调用这样的常函数 (常函数:可以保证不改变成员变量的值的函数,因为常对象的成员变量不能改变) cout<<a.m<<endl; 这样使用是可以的 a2=a1;是可以的 如果两个函数都一样,一个是带const,另一个是不带const的,那么这两个函数也可以构成重载 可以用const对象调用带const的函数, 用非const对象调用非const的函数(如果没有非const函数,也会去调用const函数),系统自动调用,我们只需要写函数名就可以了,例如上面的例子: a.print(); void print const(){} a1.print(); void print(){} mutable(易变型成员变量) mutable int m; //如果把类A中的 m 这样声明 a.m=100; //这样 const对象就可以修改成员变量 void set(int x)const{ m=x; } 这样也可以修改m的值 如果一个函数只修改了易变行成员变量也可以成为const函数 static成员变量和static 成员函数 如果定义类中的成员变量为 static int x; 这个变量会放在静态区,全局区 会被所有对象所共用 在程序启动的时候就分配了内存,x就已经存在了 静态变量是属于类的 int A::x=0; //必须在全局区初始化 以后可以这样使用A::x=100; cout<<&A::x<<endl; 只有静态的才可以这样使用 static void set(int x1){x=x1;} //静态成员函数,只能使用静态成员 也可以用类名调用A::set(123); 所以当没有对象的时候也可以调用静态函数 非静态成员函数只有对象才能调用 友元 注册一个类a(或函数)是另一个类b的友元,这个类a(或函数)就可以操作类b的私有成员和函数 友元全局函数 class A; //声明 void print(A a); //声明 class A{ friend void print(A a); //在这注册函数是类A的友元 private: int x; }; void print(A a){ //这个函数就是友元全局函数 a.x=100; cout<<a.x<<endl; } 友元成员函数 class B; //声明B类 class A{ private : public: void print_B(B b); }; class B{ friend void A::print_B(B b); //注册成B的友元函数 private: int x; public: B(){ x=0; } }; void A::print_B(B b){ b.x=1000; cout<<b.x<<endl; } A a; B b; a.print_B(b); 友元类 class B; class A{ public: void print_B1(B b); }; class B{ friend class A; private: int x; }; 继承 成员函数只有一套,但是成员变量会根据对象而有多套并分配变量内存,成员函数是存放那个代码区的 单继承:每一个子类只有一个直接父类 多继承:一个子类有多个直接父类 基类:父类 派生类:子类 class A{ public: int x; //b可以直接使用X private: int y; //b不可以直接使用y protected: int z; public: set_A(int y){ y=100; } }; class B:public A{ //一个冒号 后面加继承方式 加 父类名,继承方式只能缩小不能扩大,继承方式表明父类中的成员到子类中的访问方式 void set(){ set_A(); //可以这样使用 x=100; // 可以这样使用 y=200;// 不可以这样使用,但是可以调用A中的函数操作y } B(int x1,int y1,int m1,int n1):A(x1,y1){ //这样在定义b的时候可以调用A的有参构造函数 } }; B b; b.set_A();//可以这样使用 构造与析构 B b; //会调用A的默认无参构造函数,和析构函数 B b(1,2,3,4); //这样会调用A的有参构造函数 private和protected的区别 子类可以在子类的中函数使用父类的 protected 成员(父类的private成员,子类只有通过父类的公有成员函数才可以使用),但是不可以直接用对象调用父类的protected成员 继承机构中成员变量的隐藏 如果子类和父类中有重名的变量 A x ,y 父类 B x ,m 子类 在内存中会这样区分 A::x y x m b调用A的x: b.A::x 如果子类中有和父类同名的函数,则会默认调用子类的函数,如果想调用父类的函数需要b.A::print() 这样调用 多继承 class A{ void f(){ } }; class B{ void f(){ } }; class C:public A,public B{ //构造构造函数的调用会按照继承的顺序 A,B,C依次构造 void f(){ } }; c.f(); //调用C的f函数 c.A::f(); //调用A的f c.B::f(); //调用B的f 一个列子: .............................................................................................................. #include<iostream> using std::cout; using std::endl; class A1 { public: int x; A1(int x1):x(x1) { cout<<"A1的构造函数被执行"<<endl; } ~A1() { cout<<"A1的析构函数被执行"<<endl; } void f()const { cout<<"A1::f()被执行"<<endl; cout<<"调用者地址:"<<this<<endl; cout<<"x的地址:"<<&x<<endl; } }; class A2 { public: int x; A2(int x1):x(x1) { cout<<"A2的构造函数被执行"<<endl; } ~A2() { cout<<"A2的析构函数被执行"<<endl; } void f()const { cout<<"A2::f()被执行"<<endl; cout<<"调用者地址:"<<this<<endl; cout<<"x的地址:"<<&x<<endl; } }; class B:public A1,public A2 { public: int x; B(int x1,int x2,int x3):A2(x2),A1(x1),x(x3) //可以用这种方法(:A2(x2))来调用父类的构造函数,并传值 { cout<<"B的构造函数被执行"<<endl; } ~B() { cout<<"B的析构函数被执行"<<endl; } void f()const { cout<<"B::f()被执行"<<endl; cout<<"调用者地址:"<<this<<endl; cout<<"x的地址:"<<&x<<endl; } };............................................................................................................. virtual函数与动态多态 虚函数:virtual 父类的指针可以指向子类对象 父类的指针调用的函数是自己本类的函数 class A{ virtual void js(){ //在父类和子类的函数前都加上virtual 父类的指针就可以调用子类的函数 父类的函数与子类的函数声明必须完全相同(参数列表和返回值) , //而且参数不能有默认值(如果参数有默认治值则默认是父类的值),可以传参 } }; class B:public A{ virtual void js(){ //如果这里不写virtual 子类的这个函数也会默认是析构函数,因为是从父类继承的 } } A *p=null; p=new B; 如果父类的对象指向自己的对象 虽然加上了virtual也会调用自己的函数 父类的指针只能调用父类指针拥有的函数,和变量 在父类中写纯虚函数 virtual void js()=0; 等着子类来覆盖 抽象类 拥有纯虚函数的类 主要的作用是被子类继承,子类继承后会覆盖纯虚函数,不能生成对象 析构函数调用 delete p; 这样会析构A的析够函数,也就是父类的析构函数 如果在父类和子类析构函数前加virtual就是一起析构父类和子类的析构函数,因为调用子类的析构函数后就会自动调用父类的析够函数 有了虚函数后对象的内存空间会多4个字节,用来存放指针变量,这多出来的4个字节会从对象的首地址开始存放,对象的首地址是指针地址,不是对象的成员变量地址, 这个指针会存放虚函数表的地址, 当父类的指针指向子类的对象时,执行虚函数时,会自动到对象的首地址里面存放的指针中查找虚函数表中存放的虚函数名的首地址,再通过虚函数表中虚函数名的首地址对应代码区中函数的首地址,执行函数 每一个类都会有一个虚函数表,有虚函数才会有虚函数表 class A { public: int x; virtual void f1(){} virtual void f2(int){} }; class B:public A { int y; }; class C:public B { int z; public: virtual int f3() { return 0; } }; 虚函数表结构: 虚函数名 虚函数代码首地址 virtual void A::f(); 对应虚函数名首地址 virtual void A::f2(); virtual void B::f(); virtual void A::f2(); virtual void C::f(); virtual void B::f2(); virtual void C::f3(); 运算符重载 &a 取地址 int a=100; int &m=a;(或 int& m=a;) m就是一个引用,就是a的一个别名 cout<<m<<endl; 会输出100 template<class T> //定义一个模板 T max(T a,T b){ return a>b?a:b; } int main(){ cout<<max(1,1)<<endl; cout<<max(1.1,2.2)<<endl; return 0; }
0 0
- C语言基础整理
- C语言基础整理
- C语言基础整理
- C语言基础整理
- C++开发基础整理
- c基础部分代码整理
- C语言基础知识点整理
- 数据结构基础整理(C语言)
- 初学C语言基础整理
- JNI的C基础整理
- c/c++整理--程序基础
- C语言基础考试整理
- C语言基础整理1
- OOABAP开发基础语法整理
- LINUX开发基础整理笔记
- 基础 Android 开发规范整理
- C#Socket通信基础方法知识整理
- C/C++基础整理(1)
- 了解负载均衡 会话保持 session同步(转)
- ios开发 隐藏状态栏
- ArraySegment的使用
- mybatis之配置文件
- jdbc更新oracle时间字段问题
- C++开发基础整理
- 接口实现Fragment、Activity间互调解耦
- JAVA多线程
- 802.15.4中文版
- vector<string>字符串容器介绍
- 关系型数据库「SQLite 3.11.0」发布
- 《大话设计模式》——原则:依赖倒转原则
- 31.initWithNibName/initWithCoder/awakeFromNib/loadNibNamed联系区别
- ccf部分题目及答案