C++重要知识点拾忆

2024-09-07 18:32
文章标签 c++ 知识点 重要 拾忆

本文主要是介绍C++重要知识点拾忆,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一:内联函数

函数调用也会带来降低效率的问题,因为调用函数实际上将程序执行顺序转移到函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去前要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保存地址继续执行。
因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。特别是对于一些函数体代码不是很大,但又频繁地被调用的函数来讲,解决其效率问题更为重要。引入内联函数实际上就是为了解决这一问题。
优点:可以加快代码的执行速度,当程序中调用内联函数时,该函数直接嵌入到每个调用语句处,每次函数调用时都用相对应的一段代码代替。可见它是以目标代码的增加为代价来换取时间的节省
主要解决功能相对简单、规模不大但使用相当频繁的程序运行效率问题。
使用内联函数时,遵守以下规则:
1. 内联函数体内不能包含任何静态变量,不能使用循环语句、switch;不能递归。
2.内联函数的定义必须出现在第一次被调用之前。
3.如果函数返回类型为void,则不能有return 语句。

二:指针
通过指针引用数组元素
int a[10];
int *p;
p++是合法的,而a++是错误的。a是数组名,它是数组的首地址,是常量;

指向函数的指针变量:存放函数入口地址,指向的是程序代码存储区。
1、函数调用可以通过函数名调用,也可以通过指向函数的指针变量调用。
2、(*p) ( )表示定义一个指向函数的指针变量,在程序中把哪个函数的地址赋给它,它就指向哪一个函数。
3、给函数指针变量赋值时,只需给出函数名而不必给出参数。 p = max
4、用函数指针变量调用函数时,只需将(*p)代替函数名,在(*p)之后的括弧中根据需要写实参。 c=(*p)(a,b)
5、对指向函数的指针变量不能运算

const pointer

一个指针涉及到两个变量,一个是指针本身,另一个是指向的变量

1.指向常量的指针const放在指针类型前,在程序中不能通过指针来间接修改指针所指向的内存空间的值,但可以改变指向的空间int a = 10;const int b = 20;const int* pa = &a;const int* pb = &b;a = 100;                    // okb = 200;                   // error*pa = 100;               // error*pb = 200;              // errorpb = &a;             // okpa = &b;            // ok2.指针常量const放在”*”和指针名之间,不能改地址能改所指向的值。int b =28;
int* const pb = &b;*pb = 100;                   // ok
pb++;                       // error
在定义指针常量时,必须将其初始化。3.指向常量的指针常量const在上述两个地方都加。既不允许修改指针值,也不允许修改指针变量所指向的值
const int a = 10;
const int * const pa = &a;a = 100;    // error
*pa = 100;  // error
pa ++;  // error

三:引用

标题

引用与指针的区别引用是 C++ 语言引进的概念,在 C 语言中没有。

1)、指针是变量,引用是别名
引用是别名,引用本身没有地址。
2)、指针可作数组元素、引用不可
例: int *pa[5];//指针数组
int a[5];
int &rea[5]=a;//不可

3)、可以有空指针,不可有空引用
例: int *p=null;//合法
int &re=null;//无意义

四:类(class)

私有(private)的数据和函数,只允许本类的成员函数访问或调用;
保护(protected:)的数据和函数,允许本类和本类派生类的成员函数访问或调用;
公有(public:)的数据和函数,允许本类和其它类的函数访问或调用。

静态数据成员:
1.类的静态数据成员为该类的所有对象所共享。
2. 必须在类外文件作用域中的某个地方对静态数据成员赋初值(因为构造函数多次被调用,而静态数据成员只初始化1次):
<类型> <类名>::<静态数据成员> = <初值>

Const 成员函数中确保不会修改任何本类对象的数据成员。

class constfun
{private:int  a;public:void nonconstFunc( ){a=18;         //ok}void  Func( ) const{a=18         //error}
}
this指针:this指针是指向对象的指针,隐含在类的成员函数中,用来指向成员函数所属类的正在被操作对象。this指针可以看作是类自身的一个引用。

构造函数的调用顺序
对于构造函数,先执行基类的,再执行对象成员的,最后执行派生类的。
对于析构函数,先执行派生类的,再执行对象成员的,最后执行基类的。

导出类构造函数和析构函数的构建
基类的构造函数和析构函数不能被派生类继承。
如果基类没有定义构造函数,派生类也可以不定义构造函数,全都采用缺省的构造函数,此时,派生类新增成员的初始化工作可用其他公有函数来完成。
如果基类定义了带有形参表的构造函数,派生类就必须定义构造函数,提供一个将参数传递给基类构造函数的途径,以便保证在基类进行初始化时能获得必需的数据。
如果派生类的基类也是派生类,则每个派生类只需负责其直接基类的构造,不负责自己的间接基类的构造。
派生类是否要定义析构函数与所属的基类无关,如果派生类对象在撤销时需要做清理善后工作,就需要定义新的析构函数。

五:多重继承

解决二义性问题
解决方法一:用类名来限定(主要解决方法)   为避免二义性,可在调用时加上基类的名称,如 A::print() 或 B::print() 。
解决方法二:同名覆盖在C 中声明一个同名成员函数print(),f()再根据需要调用  A:: print()    或    B:: print()
解决方法三:使用虚函数

面向对象设计的三大机制: 数据封装、继承、多态。

  继承:研究的是类与类之间的层次关系。多态性:指不同的对象接收到相同的消息时产生不同的响应动作,即对相同的函数名,却执行不同的函数体。函数重载和运算符重载实现类的一种多态性。

静态联编和动态联编
联编(binding):是将函数调用与相应的函数体代码彼此关联的过程。
静态联编(static binding):如果联编过程在程序开始运行前的编译阶段完成。
例如:重载函数:
void fun(int a,int b)
void fun(float x,float y)
void fun(char c)
函数名字相同,但各自参数不同,编译器能根据函数参数的类型和个数自动选择相应的函数体编译。

动态联编(dynamic binding)
在程序运行时进行的联编方式。
例如:虚函数
C++中的虚函数,由于其函数名、返回值、函数参数完全相同,但函数体不同,因此编译阶段无法确定函数调用与哪个函数体关联,只能由系统在程序运行时确定。

六:虚函数

虚函数(virtual function)----运行时多态在定义某一基类(或其派生类)时,若将其中的某一函数成员的属性说明为virtual,则称该函数为虚函数。若基类中某函数被说明为虚函数,则意味着其派生类中也要用到与该函数同名、同参数表、同返回类型、但函数体不同。虚函数存在继承环境中。
虚函数成员的定义语法:virtual 函数类型 函数名(形参表){函数体}
程序举例     
class BaseClass
{public:virtual void show() {cout<<"Base class"<<endl;}//如果不加关键字virtual,运行的结果都是"Base class";
};
class Derived1:public BaseClass
{public:void show() {cout<<"Derived class1"<<endl;}
};
class Derived2:public BaseClass
{public:void show() {cout<<"Derived class2"<<endl;}
};int main(){BaseClass  obj;BaseClass   *p;Derived1   obj1;Derived2   obj2;p=&obj;p->show();p=&obj1;p->show();p=&obj2;p->show();return 0;
}通过虚函数,达到了用基类指针访问派生类对象成员函数的目的,这样,只要声明了基类指针,就可以使不同的派生类对象产生不同的函数调用,实现了程序的运行时多态。
运行多态应该使用虚函数,并通过指针、引用或者成员函数调用虚函数
          纯虚函数和抽象类

纯虚函数(pure virtual function):
在基类中声明虚拟函数而不给出具体的定义,把它的定义放在各个导出类中,此种函数为纯虚函数
通过基类指针或引用可以调用所有派生类的虚函数。

抽象类:(abstract class)
声明了虚函数的类,基类只用于继承,仅作为一个接口,具体的功能则在派生类中实现。
注意:从抽象类可以派生出具体的或抽象类,但不能从具体类派生出抽象类。

虚基类
虚基类的引入
用于有共同基类的场合
声明
以virtual修饰说明基类例:class B1:virtual public B
作用
主要用来解决多继承时可能发生的对同一基类继承多次而产生的二义性问题.
为最远的派生类提供唯一的基类成员,而不重复产生多次拷贝

类模板
C++中实现多态的另一种方法是类模板
类模板可以使用户为类定义一种模式,使得类中的一些数据成员和成员函数的参数,以及成员函数的返回值能够娶任意类型。

#include <iostream.h>
template <class T> class TestClass {  public:T buffer[10];  //T类型的数据成员buffer数组大小固定为10 (灵活性差!)    T getData(int j);       //获取T类型buffer(数组)的第j个分量 
};template <class T>  
T TestClass<T>::getData(int j) {return *(buffer+j);   
}; 
void main() {TestClass<char> ClassInstA;     //char取代T,从而实例化为一个具体的类 char cArr[6]="abcde";for(int i=0; i<5; i++)ClassInstA.buffer[i]=cArr[i];for(i=0; i<5; i++) {char res=ClassInstA.getData(i);cout<<res<<"  ";}cout<<endl; 
程序执行后的显示结果如下:
a  b  c  d  e
2.1  13.2  24.3  35.4  46.5  57.6 

既使用类型参数又使用 普通参数的类模板示例

#include <iostream.h>
#include "string.h"
template <class T, int i> class TestClass {public:T buffer[i];  //T类型的buffer,其大小随普通形参i的值变化(灵活性大!)T getData(int j);  
};template <class T, int i>  
T TestClass<T,i>::getData(int j) {return *(buffer+j);    
};
TestClass<double, 6> ClassInstF;double fArr[6]={12.1, 23.2, 34.3, 45.4, 56.5, 67.6};for(i=0; i<6; i++)ClassInstF.buffer[i]=fArr[i]-10;for(i=0; i<6; i++) {double res=ClassInstF.getData(i);cout<<res<<"  ";}cout<<endl;
}程序执行后的显示结果如下:
a  b  c  d  e
2.1  13.2  24.3  35.4  46.5  57.6

这篇关于C++重要知识点拾忆的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1145821

相关文章

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

基本知识点

1、c++的输入加上ios::sync_with_stdio(false);  等价于 c的输入,读取速度会加快(但是在字符串的题里面和容易出现问题) 2、lower_bound()和upper_bound() iterator lower_bound( const key_type &key ): 返回一个迭代器,指向键值>= key的第一个元素。 iterator upper_bou

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝

C++——stack、queue的实现及deque的介绍

目录 1.stack与queue的实现 1.1stack的实现  1.2 queue的实现 2.重温vector、list、stack、queue的介绍 2.1 STL标准库中stack和queue的底层结构  3.deque的简单介绍 3.1为什么选择deque作为stack和queue的底层默认容器  3.2 STL中对stack与queue的模拟实现 ①stack模拟实现

c++的初始化列表与const成员

初始化列表与const成员 const成员 使用const修饰的类、结构、联合的成员变量,在类对象创建完成前一定要初始化。 不能在构造函数中初始化const成员,因为执行构造函数时,类对象已经创建完成,只有类对象创建完成才能调用成员函数,构造函数虽然特殊但也是成员函数。 在定义const成员时进行初始化,该语法只有在C11语法标准下才支持。 初始化列表 在构造函数小括号后面,主要用于给