C++部分知识

 

类和对象

    类是对象的类型,对象是类的实例

    成员变量:用来区分同一个类的不同对象,可以是各种类型(简单类型。指针、引用、复合类型、其他类)

    静态成员:描述整个类的特征;非静态成员变量:描述不同对象的特征

    常量成员:必须在创建一个对象的时候初始化它的常量成员,且不能更改

    成员函数:用来操作一个类的对象的函数

    静态成员函数:属于整个类的成员函数

private 私有,把类的数据成员对外隐藏,使之从外部不可见,称为信息隐藏;成员函数是给外部的访问接口,public 公有,外部通过公有成员函数才能访问私有成员(则把对象的私有数据保护起来了,这种方式就是封装)

构造函数

    构造函数用于生成一个对象,析构函数用于销毁一个对象,get函数用于获取成员变量的值,set函数用于修改成员变量的值

    声明对象时,将自动调用构造函数:构造函数必须公有,函数名和类名一样,没有返回值,可以接收参数

    默认构造函数:不是一定没有参数,而是调用时不用传参,有且只有一个默认构造函数,但是可以有多个重载的构造函数,靠不同的参数列表来区分

    包括两种情况:构造函数本身无参数、构造函数有参数但参数都有默认值

重载函数

    函数名称一样,参数列表不同(参数类型或参数个数不同),仅仅返回值不同是不可以的

初始化列表

    在构造函数的函数头,对类的成员变量进行初始化,初始化方式【:成员变量(赋给成员变量的值) {}】。赋给成员变量的值是构造函数的形参或常数。其优势:效率高,有些类型的成员变量只能用初始化列表初始化,如常量成员、引用类型

复合类

    复合类的成员变量,是另一个类的对象

    当不需要在成员函数里修改成员变量的值时,加上const可以增加程序健壮性

析构函数

    析构函数:收回构造函数时申请的资源,垃圾回收

    两种情况会调用析构函数:离开对象的作用域;销毁对象删除一个指向对象的指针。当一个类中有指针成员变量并且指向手动开辟的堆空间时,必须写析构函数,用delete回收指针指向的内存空间,避免内存泄漏

特点:无返回值、无参、唯一、公有

浅拷贝

    可以向一个函数传递对象作为参数,对象也可以作为函数的返回值,有传值、传引用、传指针三种方式

    为了避免对象的拷贝,经常传递对象的引用,并且为了避免被修改加上const(const & x)

    如果传值方式返回,系统将创建一个临时对象,来接收返回值

    浅拷贝:逻辑拷贝,把对象赋值给另一个对象,对象每个成员的值,将一对一拷贝到新的对象,仅适用于没有指针成员的对象拷贝

    二次删除:如果对象含有指针成员变量,且指向堆上空间,将只拷贝指针成员变量本身的值,造成两个对象指向同一堆上的内存空间,删除对象时造成二次删除

    内存泄漏:如果上述情况中,对象原来含有指针成员变量且指向另一堆上空间,则赋值后,造成该内存空间泄漏,并且删除时造成二次删除

this指针

    每个对象都隐式的包含了一个成员变量,this

    this是一个指针,指向对象自己,其值是对象的地址

 

静态成员

    静态局部变量:存放在静态存储区、在两次函数调用期间保留原值仅在函数内部可见、可以被自动初始化为0

    静态全局变量:作用域仅在变量所在的文件内

    2、类的静态成员:

    2.1 静态成员的值和某一个具体对象无关

    2.2 静态成员整个类只有一份拷贝,不需要每个对象都保留一份copy(非静态成员,每个对象都有一个特定的值,每个对象都为自己的非静态成员,在内存中保留一个位置)

    2.3 访问方式  类名::静态成员名

    2.4 静态成员不应该让对象来调用(不推荐)

    2.5 必须在类声明之后,用::初始化(不在头文件初始化)

    3、静态成员函数:

    3.1 被类的所有对象共享,不是和某个特定对象而是和整个类相关联

    3.2 不可以使用this指针,因为this指针是指向每一个具体对象的,所以this指针本身是非静态成员变量

    3.3 静态成员函数只可以访问静态成员,而不能访问非静态成员,反之,非静态成员可以访问静态成员

    3.4 同样有public/private,私有静态成员函数不能在外部用类名或对象名访问,只能从类内部被其他静态成员函数访问 

3.5 导入类所在头文件,就可以让多个文件调用(用类名调用),大大减少代码书写量

深拷贝

1、操作符重载

    1.1 让同样的操作符执行不同的操作,使用操作符操作非默认类型的操作数

    1.2 const  A & operator  =  (const  A  &  x)

2、深拷贝

    2.1 避免自赋值(if(this != &x))  

       --  释放掉指针成员已经指向的内存空间,避免内存泄漏 

       --  为指针成员开辟新堆内存空间  

       --  向新内存空间拷贝内容  

       --  返回*this,即返回新对象本身

3、重载==运算符,判断两个对象的每一对成员变量是否相等:bool = true;首先判断长度是否相等,如果不等,bool = false;否则逐一比较对应元素是否相等:int i= 0;while (i < size && *(rep+i) == *(v.rep + i)){i++;} ;退出while循环后比较i和size,如果i < size,则不等

4、拷贝构造函数:通过拷贝一个已有对象来创建一个新的对象

    1、声明一个对象,并用另一个已经存在的对象初始化:

    1.1把已经存在的对象作为新声明对象的构造函数的参数

    1.2声明一个对象,并用赋值表达式,用一个已有对象来初始化它

    1.3用new运算符,在堆上创建对象,并用一个已有对象对其进行初始化时

    2、传值的方式,从函数返回一个对象:

    2.1向函数传参时,传值调用时,形参是实参的拷贝

    2.2从函数传值返回对象时,创建一个临时对象,接受返回值,会调用拷贝构造函数

三大件:拷贝构造函数、析构函数、赋值运算符的重载(实现深拷贝,避免二次删除和内存泄漏)

    如果拷贝构造函数的参数用传值的方式,那么当实参传递给拷贝构造函数的时候,拷贝构造函数的形参为了复制实参,会再次调用拷贝构造函数,形成死循环,因此拷贝构造函数的参数必须传引用

    编译器提供的析构函数,对于指针类型的成员变量,仅仅释放指针本身的内存,不释放指针指向的堆上内存,此时必须定义一个析构函数,用delete来释放堆内存

临时对象的系统开销很大,传值(包括参数、返回值)分别需要形参和返回值的临时对象调用拷贝构造函数和析构函数,传引用就显得效率,传参不需拷贝构造函数,返回时也不需要临时变量和析构。

继承

    1、子类与父类

    1.1 子类自动继承父类所有成员(包括成员函数、成员变量),除了构造函数、析构函数和重载的赋值运算符。

    1.2 子类在用父类所有功能的同时,也扩展了一些新的功能。即子类成员分为两部分,继承自父类的部分和子类独有的成员即子类自己扩展的成员。

    1.3 子类也拥有父类的私有成员,但子类不能通过自己扩展的函数来访问继承自父类的私有成员,而必须通过继承自父类的公有成员函数来访问。

    1.4 在子类中调用被覆盖的父类版本的函数时,在函数名前加Base::。

    1.5 面向对象最重要的目标:实现代码复用。通过继承子类自动拥有了父类代码,大大减少了代码书写量,十分方便维护程序(只需修改父类代码,子类就自动随着更改)

    2、覆盖与重载

    2.1 子类可以自己实现与父类成员函数原型相同(函数名、函数列表)的成员函数,称为覆盖,覆盖是函数重载的特例,覆盖一定发生在继承的过程中。

    2.2 发生覆盖时,根据调用者对象本身的类型来确定,无法根据参数列表确定。

    2.3 ------

 

    //1.重写必须继承,重载不用。

    //2.重写的方法名,参数数目相同,参数类型兼容,重载的方法名相同,参数列表不同。

    //3.重写的方法修饰符大于等于父类的方法,重载和修饰符无关。

    //4.重写不可以抛出父类没有抛出的一般异常,可以抛出运行时异常

    //重写是子类的方法覆盖父类的方法,要求方法名和参数都相同

    //重载是在同一个类中的两个或两个以上的方法,拥有相同的方法名,但是参数却不相同,方法体也不相同

    一、重写(override)

   override是重写(覆盖)了一个方法,以实现不同的功能。一般是用于子类在继承父类时,重写(重新实现)父类中的方法。

    重写(覆盖)的规则:

    1、重写方法的参数列表必须完全与被重写的方法的相同,否则不能称其为重写而是重载.

    2、重写方法的访问修饰符一定要大于被重写方法的访问修饰符(public>protected>default>private)。

    3、重写的方法的返回值必须和被重写的方法的返回一致;

    4、重写的方法所抛出的异常必须和被重写方法的所抛出的异常一致,或者是其子类;

    5、被重写的方法不能为private,否则在其子类中只是新定义了一个方法,并没s有对其进行重写。

    6、静态方法不能被重写为非静态的方法(会编译出错)。

    二、overload是重载,一般是用于在一个类内实现若干重载的方法,这些方法的名称相同而参数形式不同。

    重载的规则:

    1、在使用重载时只能通过相同的方法名、不同的参数列表实现。不同的参数列表可以是不同的参数类型,不同的参数个数,不同的参数顺序(参数类型必须不一样);

    2、不能通过访问权限、返回类型、抛出的异常进行重载;

    3、方法的异常类型和数目不会对重载造成影响;

    

    重定义(隐藏)是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

    a 如果派生类的函数和基类的函数同名,但是参数不同,此时,不管有无virtual,基类的函数被隐藏。

    b 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有vitual关键字,此时,基类的函数被隐藏。

   

    重载和重写的区别:

    (1)范围区别:重写和被重写的函数在不同的类中,必须是继承,重载和被重载的函数在同一类中。

    (2)参数区别:重写与被重写的函数参数列表一定相同,重载和被重载的函数参数列表一定不同。

    (3)virtual的区别:重写的基类必须要有virtual修饰,重载函数和被重载函数可以被virtual修饰,也可以没有。

    3、访问修饰符

    如果父类有protected类型成员,在子类中可以直接访问,不需要借助父类公有函数,但是protected类型成员对外界依然隐藏,对外就像private类型一样

    3.1 ------

public:

 1、修饰class里的成员,这些成员可以在class的内部被访问,也可以在外部被访问。

 2、公有成员可以被继承。

 3、当一个class作为父类被继承时,可以用public来修饰。如下:

 class Child: public Father

 {   };

 此时,父类中的public和protected成员都可以被子类继承,并且修饰符与父类一样。

 protected:

 1、修饰class里的成员,这些成员可以在class的内部被访问,也可以被友元类和友元方法访问,不可以在外部被访问。

 2、保护型成员可以被继承。

 3、当一个class作为父类被继承时,可以用protected来修饰。如下:

 class Child: protected Father

 {   };

 此时,父类中的public和protected成员都可以被子类继承,并且修饰符都是protected。

 private:

 1、修饰class里的成员,这些成员只可以在class的内部被访问。

 2、私有成员可以被继承,但不能被子类访问。

 3、当一个class作为父类被继承时,可以用private来修饰。如下:

 class Child: private Father

 {   };

 此时,父类中的public和protected成员都可以被子类继承,并且修饰符都是private。

继承的应用

    当两个类之间是IS-A的关系,即一个类是另一个类的特例,用继承来实现,类之间的层级关系与它们所反映的真实世界里的事物之间的关系是对应的,一般用公有继承。

    为了实现代码复用,也可以用继承,两个类之间未必存在内在联系。类A想用类B的成员,就把A声明成B的子类,A就自动拥有B的成员函数(除了那三个)

    类之间主要的两种关系:组合:一个类的对象是另外一个类的成员变量,一个类拥有另一个类,HAS-A,有一个;;继承:一个类是另外一个类的子类,IS-A,是一个

子类的三大件

    1.1 子类构造函数中,调用父类构造函数,对来自父类的那部分成员进行初始化,再初始化自己扩展的成员

    1.2 谁的成员,归谁初始化,子类无需重复完成父类部分的工作

    1.3 父类构造函数放在初始化列表

    1.4 如果在子类的构造函数中,不显式的调用父类构造函数,将自动调用父类的默认构造函数(前提是有默认构造函数)

    1.5 如果在子类的构造函数内部,调用父类构造函数,会创建一个局部的Base对象,而子类对象自己的成员并没有被参数初始化

    1.6 析构函数无需参数,在子类的析构函数中,父类的析构函数将被自动调用

    1.7 在拷贝构造函数里,也是父类成员归父类初始化

1.8 构造子类时,先父类后子类;析构子类时,先子类后父类

虚函数与多态

1、虚函数

    1.1 当父类指针或引用指向子类对象,而子类中又覆盖了父类的函数,希望用父类指针或引用调用到正确版本的成员函数,需要把该成员函数声明为虚函数

    1.2 调用虚函数时,到底调用哪个版本,是根据调用该函数的对象本身的类型,而不是指向那个对象的指针或引用的类型,即对象的内存空间为谁(父类or子类)开辟就调用谁的成员方法或成员变量

    1.3 虚函数目的:父类指针或引用,不管指向父类还是子类,在调用覆盖函数时,可以反映真实情况;有了虚函数,无需向下转型,就可以正确的用父类的指针或引用调用到子类的函数

    1.4 如果函数的参数是传值方式,形参是父类对象,实参是子类对象,则在函数内部,用形参调用的成员函数,依然是父类版本。因为传值只是用子类对象给父类对象赋值,父类对象不是指向子类的引用或指针

    1.5 如果一个虚函数被其他成员函数调用,子类的版本也会被正确调用

    1.6 如果一个类有子类,则这个父类的析构函数必须是虚函数,即虚析构。如果不是虚析构,则当(用 delete)删除一个指向子类对象的父类指针时,将调用父类版本的析构函数,子类只释放了来自于父类的那部分成员变量,而没有释放子类扩展的成员变量,造成内存泄漏。

    1.7 如果子类的成员函数是虚函数,则子类覆盖后,不写virtual也是虚函数。

    1.8 虚函数被调用的时候,到底调用哪个版本,在编译的时候无法确定,只有在执行时才能确定,称为动态绑定。之前的函数调用,是在编译时就可以确定调用哪个版本的函数

    1.9 动态绑定使得程序可以照顾到未来增加的代码,比如创建一个新的子类,并在子类中覆盖了父类的虚函数,用之前的父类指针依然可以正确的调用到新子类中的函数,而无需对旧有代码进行修改。

2、抽象基类、纯虚函数

    2.1 纯虚函数,没有函数体,不需要实现,在子类中实现纯虚函数的具体功能

    2.2 拥有纯虚函数的类,称为抽象类,抽象类提供了不同种类对象的一个通用接口。

    2.3 不能创建抽象类的对象,因为抽象类里面的纯虚函数没有实现。

    2.4 抽象类只能作为基类使用,即抽象基类,如果想创建子类对象,必须实现抽象基类中的所有纯虚函数,否则,子类依然是抽象类

    2.5 不能单独调用抽象类的构造函数,仅可以用于子类构造函数的初始化列表里,用于初始化子类中继承自父类的成员变量

    2.6 抽象类不是必须有析构函数,一旦有,必须是虚析构

    2.7 不能以传值的方式,向一个函数传递抽象基类的参数。如果函数形参是抽象类,实参是子类,就相当于用子类对象,创建了一个临时的抽象基类对象,后者是不允许的,所以必须以传引用或指针的方式来传参

3、多态:用父类的指针或引用指向子类的对象,在函数调用时可以调用到正确版本的函数

    3.1 用一个父类的指针指向一个子类对象

    3.2 用一个父类的指针当函数的形参,用这个指针可以接受到任何它的子类对象也包括他自己

    3.3 在复合类,尽量饮用高层次的类(父类的指针)当做类的成员变量,这样就可以通过它创建出它所对应的任何子类对象包括他自己

    3.4 在容器中,可以声明一个父类指针的容器,这时可以往容器中添加它所对应的任何子类对象包括他自己

4、多态的类别及实现方法

    4.1 静态多态:编译时多态、函数的多态性,主要通过重载、模板、宏实现

    4.2 动态多态:运行时多态、类的多态性,主要通过继承和虚函数实现,(晚绑定、动态绑定) 

    4.3 封装可以使得代码模块化,继承可以扩展已存在的代码,他们的目的都是为了代码重用。而多态的目的则是为了接口重用。也就是说,不论传递过来的究竟是哪个类的对象,函数都能够通过同一个接口调用到适应各自对象的实现方法。

 

描述内存分配方式以及它们的区别?

1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。 

2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。 

3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由程序员决定,使用非常灵活,但问题也最多

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值