C++语法知识点

本文围绕C++展开,介绍了类的三大特性(封装、继承、多态)及多态实现条件,阐述了虚函数表、拷贝构造和赋值的区别,还讲解了参数传递方式、构造与析构函数、const关键词的使用,以及访问私有成员的方法、内存分配与释放函数差异、宏和内联函数区别等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

类的三大特性

封装、继承、多态
多态的实现条件:子类重写父类的虚函数,父类的指针或引用指向子类,当调用该重写的函数时,调用子类的函数而不是父类的函数。当有多个子类时,通过不同子类调用该函数,产生不同的行为,表现为多态。

虚函数表

每一个有虚函数的类都有一个虚函数表(简称:虚表)。有虚函数的类定义的对象有一个虚函数表指针(简称:虚表指针),该虚表指针指向虚函数表,虚函数表中存储的是虚函数的地址。
多态的实现:发生在父子类之间,父类中定义virtual声明的虚函数,子类继承父类,并重写虚函数。定义的对象满足父类的指针或引用指向子类,子类对象的虚函数表中存储的虚函数地址如果是子类自己定义的新的虚函数,则虚函数的地址指向子类的函数地址;如果子类重写父类的虚函数,则虚函数地址指向子类的函数地址;如果存在子类未重写的继承自父类的虚函数,则虚函数地址指向父类的函数地址。

拷贝构造和拷贝赋值

两者的本质区别:是否有新对象的产生,拷贝构造的本质是个构造函数,会产生新的对象,而拷贝赋值只是将数值赋值给一个已经存在的对象,不会产生新的对象。

class A{
A(A & a){}//拷贝构造
};

拷贝构造函数的参数必须是引用类型,如果采用值类型,类的非指针或引用对象作为参数,会引起拷贝构造函数的调用,而本身就是在定义拷贝构造函数,如此会引起拷贝构造函数的递归调用,一旦遇到使用拷贝构造的地方会引起函数的无限递归调用而崩溃。
**拷贝构造被调用的几种情况:**对象的非指针或引用方式作为函数的返回值;对象的非指针或引用方式作为函数的参数;用一个对象去创建另一个对象。
为什么要避免拷贝构造函数的调用:会引起新对象的创建,效率低,资源消耗多;如果类中有指针类型的成员,又没有处理好深拷贝浅拷贝的问题,会引起错误。
深拷贝浅拷贝的问题:提供的默认拷贝构造函数是浅拷贝函数,调用时将对象中的数据进行逐字节拷贝,如果类中的成员变量都是非指针类型的变量,使用默认的拷贝构造函数是没问题的,但是如果有指针类型的成员变量,此时默认的拷贝构造函数,在执行到对该变量的数值处理时,是将指针的值直接赋值给要创建的对象,此时就会出现一个问题,原对象的指针和新创建的对象中的指针类型的成员变量指向同一块地址,当释放其中一个对象时,指针类型的成员变量会将指向的内存进行释放,但是此时另一个对象指针类型的成员变量仍指向那块内存,当释放两一个对象时,又会释放一次该内存,引起double free,所以在一个类中有指针类型的成员变量时需要自己重写拷贝构造函数,将指针类型的成员分配与原对象一样的内存,然后把数据拷贝到新创建的内存中,也就是所谓的深拷贝,这样前后两个对象分别指向不同的内存块,避免了double free问题的发生。

参数传递的几种方式

值传递: 使用时会将值复制一份,将复制的值传递到被调用的函数中进行使用,参数在被调用函数中的修改不会影响外部函数中的值
指针传递: 为值取一个别名传递给被调用函数使用,在函数中对参数值的修改会引起外部函数中数值的修改
应用传递: 创建一个指针,指向原来的地址,将这个指针作为参数传递给被调用函数使用,数值在被调用函数中的修改会引起外部函数中数值的修改
指针和引用的异同: 同:都可以对所指向的对象进行修改
异:指针是变量,内容是一个地址;引用只是为对象起了一个别名;
指针可以在声明的时候不进行赋初值,引用在声明的时候必须赋初值;
指针可以改变指向的对象,引用不可以;
指针可以为空,引用不可以为空;
可以有多级指针,没有多级引用;
++操作不一样;
求sizeof不一样,指针求sizeof为常量4,而对引用求sizeof是引用对象所占用的内存大小。

构造函数和析构函数

构造函数可以重载,析构函数不可以重载
构造函数和析构函数都可以抛异常,一般在构造函数中有内存申请异常的情况下需要抛异常处理;不推荐析构函数抛出异常,有可能导致后续内存的释放没有被执行而出现内存泄漏的问题。
当实现多态时,父类的析构函数需要声明为虚析构,父类的指针或引用指向子类,对象的类型会被当做父类的类型来处理,如果父类的析构函数不声明为虚析构,且此时子类中存在指针类型的成员变量,释放该对象时只会调用到父类的析构函数,子类的析构函数不会被调用到,从而造成内存泄漏,如果父类声明为虚析构,通过虚函数表会调用子类的析构函数,从而避免了内存泄漏的问题。

C++中的const关键词

const是一种修饰,被const修饰的内容不能被修改。
const修饰其前面的信息,如果前面没有信息则修饰紧随其后的信息。
const修饰普通变量,需要在声明变量的时候进行初始化,且初始化后不能通过该变量改变数据的值。
const修饰形参,表示参数在函数内不能被修改。
const修饰函数,表示在函数中不会对访问的数据进行修改。
const修饰成员变量,可以通过初始化参数列表进行数据初始化,C++11中可以直接进行初始化。
类的const对象,可以访问类的const成员函数,不能访问非const成员函数。
类的非const对象,可以访问类的const成员函数和非const成员函数。
类的const成员函数,只能调用类的const成员函数,不能调用非const成员函数
类的非const成员函数,可以调用类的const成员函数和非const成员函数

外部可以访问类的私有成员变量的几种方式

  • 类中封装访问私有成员变量的方法
  • 声明友元函数 friend(友元函数不属于类的成员函数)
  • 友元类

new、malloc;delete、free;delete、delete[];delete、deleteLater

new、malloc;delete、free的异同:new和malloc都可以分配内存,delete和free都可以释放内存
new和delete是运算符,而malloc和free是函数;new会返回数值的类型,会自动计算所需内存的大小,malloc返回值不带类型,需要进行类型转换,并且需要指定开辟内存的大小;new会自动调用相应的构造函数,delete会调用相应的析构函数,但是malloc和free不会

delete和delete[]的区别
delete用于释放单个对象指向的内存;delete[]用于释放一组对象指向的内存。

delete和deleteLater的区别
Qt中delete和deleteLater都可以删除一个对象
delete会直接删除对象,deleteLater会在对象不会使用的时候才被删除,一般在多线程的时候,防止线程退出时对象还在使用,直接删除造成程序崩溃,而使用deleteLater

宏和inline函数的区别

  • 内联函数在编译期展开,宏在预编译期展开
  • 内联函数是函数,宏不是函数
  • 内联函数有语法检测和类型检查,宏没有
  • 内联函数直接嵌入到目标代码中,而宏只是简单的文本替换
  • 宏定义时需要注意括号的使用,防止出现歧义,内联函数不需要
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值