经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
c++面向对象程序设计总结(类的使用)
来源:cnblogs  作者:两千个秘密  时间:2018/10/15 9:26:58  对本文有异议

本篇算是学习c++有关类的知识的一些易错点吧.....

并不是特别详细,以后会更新吧....

几点并不关于类的东西

1.函数模板,用虚拟类型来实现模板的功能

  1. #include<iostream>using namespace std;
  2. template <typename t>//t为虚拟类型的名字,自己起的t maxx(t a,t b,t c)
  3. {return max(a,max(b,c));
  4. } 
  5.  
  6. int main()
  7. {double a=1.1,b=2.2,c=3.3;//不管为double 还是int都可以调用maxx cout<<maxx(a,b,c)<<endl;int a1=1,b1=2,c1=3;
  8.     cout<<maxx(a1,b1,c1)<<endl;
  9.  }

2.关于函数默认的参数值要放到最右边

  1. void f1(float a,int b=0,int c,char d='a');//错误,void f2(float a,int c,int b=0,char d='a');//正确

3.内置函数

函数最左边加上inline(我觉得没啥用),规模很小的函数才用

4.字符串

sizeof(string) 为4,因为系统分配的是固定的字节数,存放的是字符串的地址

.......(以后再补充把)

 

 

开始类的学习

1.三种类的类型

public

这个就不多说了,类的对外接口

private

想要访问只能通过该类中的函数来访问

protected

和private差不多,区别在于继承时,以后说

 

2.类的声明和成员函数的分离(以后更新)

 

3.构造函数

没有返回值,名字和类名字一样#include<iostream>

  1. using namespace std;class box{public:
  2.        box(int ,int ,int );//构造函数 (有无默认参数都行)int volume();private:int h;int w;int l;
  3. };
  4. box::box(int a,int b,int c)
  5. {
  6.    h=a,w=b,l=c;
  7. }//其实一般这样写// box::box(int a,int b,int c):h(a),w(b),l(c){}
    //注意如果是数组的话  则要写在大括号内
    //box::box(int a,int b,int c,char nam[]):h(a),w(b),l(c)
    //{strcpy(name,nam);}

可以用另一个对象初始化另一个

time t1;

time t2=t1;   //注意是吧t1的数据成员复制到t2,而不调用t2的构造函数

4.析构函数

注意一点,先构造的后析构,相当于栈,先进后出

静态局部对象,在函数结束时,并不释放,也就不调用析构函数

5.对象数组

box b[3] = (1 , 2 ,3)//这样其实不对,这三个实参则分别作为3个元素的第一个实参

初始化应该

  1. box a[3]={
  2.     box(10,20,30);
  3.     box(20,30,40);
  4.     box(1,2,3);
  5. }

6.对象指针

先说下函数指针。。。。还有函数指针????

类型名(* 指针变量名)(参数列表)

  1. void (* p)();//p是一个指向void型函数的指针 p=fun;//fun函数入口地址付给p 注意没有括号(*p)();

对象成员函数有些复杂

要求    函数参数类型和个数匹配        函数返回值类型一样     所属的类一样

void ( time:: *p )();//此时p为指向time类中的成员函数指针

  1. time t; void (time:: *p)();
  2.  p = &time::gettime();
  3.  (t.*p)();

7.this指针(指向当前对象)

当前被调用的成员函数所在对象的起始地址

  1. int box::volume()
  2.  {return (h*l*w);}//实际为{ return this->h * this->l * this->w;}

调用时 如 a.volume() ,实际为将对象a的地址传给形参this指针

 

8.常对象
只能通过构造函数参数表来对其初始化,所有数据成员绝对不能被改变,并且只能调用它的常成员函数
如果非要改变,要加上 mutable 如有一个计数变量count,  则要  mutable int count;

非const数据成员   非const函数可引用和改变   const函数可引用不可改变
const数据成员   非const函数可引用不可改变   const函数可引用不可改变
const函数不可调用非const函数

常指针 如  
Time t1;
Time * const p = =&t1;
p不可再改变
常变量只能被常指针指向,,
普通变量也可被常指针指向,但这时该普通变量就在这期间变成的常变量,不能改变

复制构造函数
Box box2(box);


9.静态数据成员

数据声明前 加 static
特点是可以被每个该同类对象所引用,只能在类体外进行初始化,在类外也可直接引用
如  int Box::height = 10;//不必加static
可以通过对象名来引用,也可以通过类名
如  
cout<<a.count<<endl;
cout<<Box::count<<endl;

10.友元
友元函数可以使一般的,也可以是另一个类中的,可以访问私有数据成员
友元类就是全家都是友元函数
注意是单向的,注意不能传递

11.类的模板

  1. temple<class t>//t 为虚拟变量名字 可以有多个,但都要加class 如:temple<class t1,class t2> class compare{public:
  2. compare(t a,t b)
  3. {
  4. x=a,y=b;
  5. }
  6. t max() {return max(a,b);
  7. }private:
  8. t x,y;
  9. };


定义对象时为:
compare<int> cmp(3,4);
//多个时 compare<int ,double> cmp(3,4);


12.对运算符的重载

  1. class yuan{public:
  2.         yuan(double a,double b):x(a),y(b){};
  3.         yuan operator +(yuan &t)
  4.         {return yuan(x+t.x, y+t.y);
  5.         }private:double x,y;
  6. };

此时如果有
yuan c1(1,2),c2(1,2),c3;
c3 = c1 + c2;
则实际为  c3 = c1.operator(c2);

但其实我觉得更方便的是通过友元函数

  1. class yuan{public:
  2.         yuan(double a,double b):x(a),y(b){};
  3.         friend yuan operator +(yuan &t1,yuan &t2)//这个其实挺灵活的,可以自行改变         {return yuan(t1.x+t2.x, t1.y+t2.y);
  4.         }private:double x,y;
  5. };

c3 = c1 + c2 则解释为operator +(c1,c2);

 

13.继承

派生类拥有基类的数据成员,其分配如下

先说公有继承

 

基类属性                               派生类    

private                                  不可访问

 

public          公有继承后        public

 

protected                            protected

 

私有继承

基类属性                               派生类    

private                                  不可访问

 

public          私有继承后        private

 

protected                            private

保护继承

保护成员:只有子女(派生类)可以访问,(友元函数也不行)

基类属性                               派生类    

private                                  不可访问

 

public          保护继承后        protected

 

protected                            protected

 

14.有子对象的派生构造函数

  1. #include<iostream>using namespace std;class Student{public:void display();
  2.         Student(int n,string nam):num(n),name(nam){}protected:int num;string name;
  3. };class Student1: public Student{public:
  4.         Student1(int n,string nam,int n1,string nam1,int a,string ad):
  5.             Student(n,nam),monitor(n1,nam1),age(a),addr(ad){}//注意初始化,一般用初始化表来 ,同样的,在多级派生中也是如此来构造void show()
  6.         {
  7.             monitor.display();
  8.         }protected:
  9.         Student monitor;//派生类中的子对象 int age;string addr;
  10. };int main()
  11. {
  12.     
  13.  }

 多级的形式

派生类构造名: 基类1构造函数(参数表) , 基类2构造函数(参数表) , 基类3构造函数(参数表) 

{  派生类中新增的数据成员初始化语句 }

15 . 关于多重继承的二义性问题

就是继承的函数名  和   派生的函数名一样了

假设有类A和类B,此时类C同时继承类A和类B,现在问题是  类A 类B  类C都有一个  叫display()的函数 

C c1;

c1.display()//此时该是谁呢,是最新的也就是c的display()。这个会覆盖

此时要想访问A的display(),则要限定作用域 。

比如  c.A::display();

16.虚基类

 

D 是 B 和 C 的派生类,B 和 C 又都是继承了A,这样会保留多份数据成员的拷贝

虚基类是的在继承简介共同基类时只保留一份

  1. class A
  2. {
  3.     A(int i){}
  4.     .....
  5. };class B: virtual public A
  6. {
  7.     B(int n):A(n){}
  8.     ...
  9. };class C: virtual public A
  10. {
  11.     C(int n):C(n){}
  12.     ...
  13. };class D:public B,public C
  14. {
  15.     D(int n):A(n),B(n),C(n){}//这个必须由最后的派生类中对直接基类和虚基类初始化
  16. }

 

17.类型的转化

派生类可以向基类对象赋值  (大材小用),也可以向积累对象的引用进行赋值或初始化

派生类对象的地址可以赋给基类对象的指针变量,也就是说,指向基类对象的指针变量也可以用来指向派生类对象

18.多态性

分为两种 ,静态多态性和动态多态性(啥玩意啊,玩的怪花(小声bb))

静态多态性 就是  函数重载   和运算符的重载

动态  就是通过虚函数来实现的

 

 说一下虚函数,作用还是要解决继承中的二义性问题,

解决方法是想通过指针的方法来实现

  1. Student stu(...);
  2. Graduate grad(...);//假设grad是stu的派生,且两者都有display函数
  3. Student *= &stu;
  4. p->display();
  5. = &grad;//想通过变换指针指向来,但单单的这样做是不行的,因为这样做会把grad类型强制转化成student的类型 p->display();

解决上述问题的方法是将Student类中的display()函数前加上virtual

  注意问题是  成原函数 定义为虚函数后,其派生类都为虚函数

  使用方法是指向一个基类对象的指针变量,并使它指向同一类族中需要调用该函数的对象

 

19.虚析构函数

如下面代码

  1. class Point{public:
  2.         point();~point();
  3. }; 
  4. class Circle: public Point
  5. {public:
  6.         Circle();~Circle();
  7. }int main()
  8. {
  9.     Point *= new Circle;delete p;return 0;
  10. }

new的一个对象,在释放的时候,只会执行基类的析构函数,而不执行派生类的

解决方法是  在Point 的析构函数前加上 virtual

个人理解(这个virtual  在继承中 都会遗传)

20.纯虚函数

先说一点吧,往往有一些类,他们不用来生成对象,唯一目的就是用它去建立派生类,叫做抽象类

比如,点 可以派生出 园 ,圆可以派生出圆柱体  ,但这些都是 shape 的直接派生或者间接派生

比如

  1. class Shape{public:virtual float area() const {return 0.0;}//虚函数virtual float volume() const {return 0.0;}//虚函数virtual void shapeName() const = 0; // 纯虚函数 形式为 virtual 函数类型 函数名字 (参数列表) =0;};

最后来个差不多的

  1. #include<iostream>using namespace std;class Shape
  2. {public:virtual float area() const {return 0.00;}virtual float volume() const {return 0.00;}virtual void ShapeName() const = 0;
  3. };class Point: public Shape
  4. {public:
  5.         Point(float a=0,float b=0): x(a), y(b){};void SetPoint(float a,float b)
  6.         {
  7.             x=a,y=b;
  8.         }float getX() const {return x;}float getY() const {return y;}        virtual void ShapeName() const {cout<<"point"<<endl;}
  9.         friend ostream &operator <<(ostream &,const Point &);protected:float x,y;
  10. };
  11. ostream &operator <<(ostream &output,const Point &p)
  12. {
  13.         output<<"["<<p.x<<","<<p.y<<"]"<<endl;return output;
  14. }class Circle: public Point
  15. {public:
  16.         Circle(float x=0,float y=0,float r=0):Point(x,y),radius(r) {}        void SetRaidus(float r){ radius = r;}        float GetRadius() const {return radius;}        virtual float area() const{ return 3.14 * radius * radius;}        virtual void ShapeName() const {cout<<"Circle"<<endl;}
  17.         
  18.         friend ostream &operator <<(ostream &,const Circle &);protected:float radius;
  19. };
  20. ostream &operator <<(ostream &out,const Circle &c)
  21. {out<<"["<<c.x<<" "<<c.y<<"]"<<endl;out<<"r="<<c.radius<<endl;return out;
  22. }class Yuan: public Circle
  23. {public:
  24.         Yuan(float x=0,float y=0,float r=0,float h=0):Circle(x,y,r),height(h){}        void SetHeight(float h) {height = h;}        virtual float area() const {return 2 * Circle::area() + 2 * 3.14 * radius * height;}        virtual float vulume() const {return Circle::area() * height;}        virtual void ShapeName() const {cout<<"Yuan"<<endl;}
  25.         
  26.         friend ostream &operator <<(ostream &,const Yuan &);protected:float height;
  27. };
  28. ostream & operator <<(ostream &out,const Yuan &Y)
  29. {out<<"["<<Y.x<<" "<<Y.y<<"],r="<<Y.radius<<"H="<<Y.height<<endl;return out;
  30. }int main()
  31. {
  32.     Point point (3.2,4.5);
  33.     Circle circle(2.4,1.2,5.6);
  34.     Yuan yuan(3.4,6.4,5.2,10.5);
  35.     point.ShapeName();
  36.     cout<<point<<endl;
  37.     
  38.     circle.ShapeName();
  39.     cout<<circle<<endl;
  40.     
  41.     yuan.ShapeName();
  42.     cout<<yuan<<endl;
  43.     
  44.     Shape *pt;
  45.     pt=&point;
  46.     pt->ShapeName();
  47.     
  48.     pt=&circle;
  49.     pt->ShapeName();
  50.     pt=&yuan;
  51.     pt->ShapeName();return 0;
  52. }

可能以和还会更新吧..............

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号