【C++】从C语言到C++学习指南

如果你也是从C语言一路过来的,那么请一起看下去吧!

文章目录

  • 面型对象程序设计
  • C++基础
    • C和C++一些语法区别
    • C++在非对象方面对C语言的扩充
    • C++的一些标准(兼容旧标准)

首先,在C++的学习中,我们要时刻清醒一点:虽然C++与C语言有很大区别,但C++是C语言的扩充

说到C++和C语言的区别,那也是面向对象和面向过程的区别,这时你的老师可能会这么给你讲:

在这里插入图片描述

可是学了C语言没学过C++的人发问了:我们在学面向过程设计的时候,说“数据和操作往往都是分离的”,数据是米饭,操作是米饭上盖的菜,既然如此面向过程那不应该是盖饭吗?而面向对象具有封装的特点更是炒饭呀!(老师气的脸都绿了)

只有当你亲口尝了这两种饭菜,你才会知道盖饭中的菜是什么米是什么,炒饭中的菜是什么米是什么,以及他们的口味。所以,当你正确的理解了这个比喻,你便能真正认识C语言与C++,面向过程和面向对象,那么请跟随我一起去寻找我们的答案吧~

面型对象程序设计

面向过程是这样的:

img

一个程序是一道菜,面向过程这道菜的特点是:先从整体角度全面看待问题,然后列出解决问题需要的步骤,再逐步去完善。

面向对象是这样的:

img

面向对象这道菜有两个主要的结构特点:①程序一般由类的定义(属性)和类的使用(行为)两部分组成;②程序中的一切都是通过向对象发送消息来实现的,对象接收到消息后,启动有关方法完成相应的操作。

  • 对象:描述其属性的数据以及对这些数据施加的一组操作封装在一起构成的统一体。对象可认为是数据+操作。
  • :类是具有相同的数据和相同的操作的一组对象的集合。
  • 消息传递:对象之间的交互。
  • **方法:**对象实现的行为称为方法

面向对象程序设计的基本特征:抽象、封装、继承、多态。


理清了面向对象和面向过程之间的区别后,然我们来了解一下——从C语言到C++~

C++基础

C++的产生和特点

C++是美国贝尔实验室的Bjarne Stroustrup博士在C语言的基础上,弥补了C语言存在的一些缺陷,增加了面向对象的特征,于1980年开发出来的一种面向过程性与面向对象性相结合的程序设计语言。最初他把这种新的语言称为“含类的C”,到1983年才取名为C++。

相比C语言,C++的主要特点就是增加了面向对象机制!

一个简单的C++示例程序

#include<iostream>                 //编译预处理命令
using namespace std;               //使用命名空间void Log(const char* message) {    //函数定义cout << message << endl;
}int main() {Log("Hello World!");cin.get();
}

C和C++一些语法区别

1.三目运算符:在C语言中返回的是一个常量,是不能被赋值的;而C++中返回的是变量,可以被赋值

2.C++中的函数必须要写返回值类型

3.在全局下,C++不允许int a;int a=10;等这种重定义二义性操作

4.在C++中不要返回局部变量或临时变量的地址,虽然C++能够运行变量出作用域之后再使用一次,即C++允许在代码块中的任何地方声明局部变量。

5.C语言中const修饰的变量不能定义数组大小,而C++中可以

const int a=10;
float arr[a];
12

6.C++中定义结构体类型变量可以不用写结构体类型名

7.关于C语言有没有bool类型:C语言的布尔类型(bool)

C++在非对象方面对C语言的扩充

(1)输入和输出

int i;
float f;
cin >> i;
cout << f;
------------
scanf("%d", &i);
printf("%f", f);
----------------
连续读入
cin >> a >> b >> c;

【cin】

  • 在默认情况下,运算符“>>”将跳过空白符,然后读入后面与变量类型相对应的值。因此,给一组变量输入值时可用空格符、回车符、制表符将输入的数据间隔开。
  • 当输入字符串(即类型为string的变量)时,提取运算符“>>”的作用是跳过空白字符,读入后面的非空白字符,直到遇到另一个空白字符为止,并在串尾放一个字符串结束标志‘\0’。

(2)const修饰符

在C语言中,习惯使用#define来定义常量,例如#define PI 3.14,C++提供了一种更灵活、更安全的方式来定义常量,即使用const修饰符来定义常量。例如const float PI = 3.14;

const可以与指针一起使用,它们的组合情况复杂,可归纳为3种:指向常量的指针、常指针和指向常量的常指针。

  • 指向常量的指针:一个指向常量的指针变量。

    const char* pc = "abcd";
    该方法不允许改变指针所指的变量,即pc[3] = ‘x';   是错误的,
    但是,由于pc是一个指向常量的普通指针变量,不是常指针,因此可以改变pc所指的地址,例如pc = "ervfs";
    该语句付给了指针另一个字符串的地址,改变了pc的值。
    123456
    
  • 常指针:将指针变量所指的地址声明为常量

    char* const pc = "abcd";
    创建一个常指针,一个不能移动的固定指针,可更改内容,如pc[3] = 'x';
    但不能改变地址,如pc = 'dsff';  不合法
    12345
    
  • 指向常量的常指针:这个指针所指的地址不能改变,它所指向的地址中的内容也不能改变。

    const char* const pc = "abcd";
    内容和地址均不能改变
    12
    

说明:

  1. 如果用const定义整型常量,关键字可以省略。即 const in bufsize = 100const bufsize = 100等价;
  2. 常量一旦被建立,在程序的任何地方都不能再更改。
  3. 与#define不同,const定义的常量可以有自己的数据类型。
  4. 函数参数也可以用const说明,用于保证实参在该函数内不被改动。

(3)void型指针

void通常表示无值,但将void作为指针的类型时,它却表示不确定的类型。这种void型指针是一种通用型指针,也就是说任何类型的指针值都可以赋给void类型的指针变量

需要指出的是,这里说void型指针是通用指针,是指它可以接受任何类型的指针的赋值,但对已获值的void型指针,对它进行再处理,如输出或者传递指针值时,则必须再进行显式类型转换,否则会出错。

    void* pc;int i = 123;char c = 'a';pc = &i;cout << pc << endl;         //输出指针地址006FF730cout << *(int*)pc << endl;  //输出值123pc = &c;cout << *(char*)pc << endl; //输出值a

(4)内联函数

在函数名前冠以关键字inline,该函数就被声明为内联函数。每当程序中出现对该函数的调用时,C++编译器使用函数体中的代码插入到调用该函数的语句之处,同时使用实参代替形参,以便在程序运行时不再进行函数调用。引入内联函数主要是为了消除调用函数时的系统开销,以提高运行速度。

说明

  • 内联函数在第一次被调用之前必须进行完整的定义,否则编译器将无法知道应该插入什么代码
  • 在内联函数体内一般不能含有复杂的控制语句,如for语句和switch语句等
  • 使用内联函数是一种空间换时间的措施,若内联函数较长,较复杂且调用较为频繁时不建议使用
#include <iostream>
using namespace std;inline double circle(double r)  //内联函数
{double PI = 3.14;return PI * r * r;
}int main() 
{for (int i = 1; i <= 3; i++)cout << "r = " << i << " area = " << circle(i) << endl;return 0;
}

使用内联函数替代宏定义,能消除宏定义的不安全性

(5)带有默认参数值的函数

当进行函数调用时,编译器按从左到右的顺序将实参与形参结合,若未指定足够的实参,则编译器按顺序用函数原型中的默认值来补足所缺少的实参。

void init(int x = 5, int y = 10);
init (100, 19);   // 100 , 19
init(25);         // 25, 10
init();           // 5, 10
1234
  • 在函数原型中,所有取默认值的参数都必须出现在不取默认值的参数的右边

    int fun(int a, int b, int c = 111);
    1
    
  • 在函数调用时,若某个参数省略,则其后的参数皆应省略而采取默认值。不允许某个参数省略后,再给其后的参数指定参数值。

(6)函数重载

在C++中,用户可以重载函数。这意味着,在同一作用域内,只要函数参数的类型不同,或者参数的个数不同,或者二者兼而有之,两个或者两个以上的函数可以使用相同的函数名

#include<iostream>
//以下函数均构成重载
int plus(int a, int b) {return a + b;
}
int plus(int a, int b, int c) {return a + b + c;
}
double plus(double a,double b) {return a + b;
}
double plus(int a, double b) {return a + b;
}
double plus(double a, int b) {return a + b;
}
int main() {std::cout << plus(2, 3) << std::endl;std::cout << plus(1,2,3) << std::endl;std::cout << plus(2.5, 5.3) << std::endl;std::cout << plus(3,4.5) << std::endl;std::cout << plus(3.3,6) << std::endl;
}

说明:

  • 调用重载函数时,函数返回值类型不在参数匹配检查之列。因此,若两个函数的参数个数和类型都相同,而只有返回值类型不同,则不允许重载。

    int mul(int x, int y);
    double mul(int x, int y);
    12
    
  • 函数的重载与带默认值的函数一起使用时,有可能引起二义性

    int fun(int a){};
    int fun(float a){};
    

从函数重载的重载条件来看,构成重载,编译不会有问题,但在调用时,如果调用方式如:fun(2.3);

由于在C/C++中的浮点型常量默认是double类型,而double类型既可以给int型变量赋值,又可以给float型变量赋值

赋值兼容(隐式类型转换)所导致的函数重载二义性问题
→解决方法
int fun(double a){}加入新的重载函数,使得类型有确定的调用方式,不存在赋值兼容

fun((int)2.3);明确函数调用时的参数类型,可以使用强制类型转换

(7)作用域标识符::

通常情况下,如果有两个同名变量,一个是全局的,另一个是局部的,那么局部变量在其作用域内具有较高的优先权,它将屏蔽全局变量。

如果希望在局部变量的作用域内使用同名的全局变量,可以在该变量前加上“::”,此时::value代表全局变量value,“::”称为作用域标识符。

#include <iostream>
using namespace std;int value;   //定义全局变量valueint main() 
{int value;  //定义局部变量valuevalue = 100;::value = 1000;cout << "local value : " << value << endl;cout << "global value : " << ::value << endl;return 0;
}

(8)强制类型转换

可用强制类型转换将不同类型的数据进行转换。例如,要把一个整型数(int)转换为双精度型数(double),可使用如下的格式:

int i = 10;
double x = (double)i;int i = 10;
double x = double(i);
12345

以上两种方法C++都能接受,建议使用后一种方法。

(9)new和delete运算符

程序运行时,计算机的内存被分为4个区:程序代码区、全局数据区、堆和栈。其中,堆可由用户分配和释放。C语言中使用函数malloc()free()来进行动态内存管理。C++则提供了运算符newdelete来做同样的工作,而且后者比前者性能更优越,使用更灵活方便。

指针变量名 = new 类型int *p;p = new int;
delete 指针变量名delete p;
12345

下面对new和delete的使用再做一下几点说明:

  • 用运算符new分配的空间,使用结束后应该用也只能用delete显式地释放,否则这部分空间将不能回收而变成死空间。

  • 在使用运算符new动态分配内存时,如果没有足够的内存满足分配要求,new将返回空指针NULL)。

  • 使用运算符new可以为数组动态分配内存空间,这时需要在类型后面加上数组大小。

    指针变量名 = new 类型名[下标表达式];
    int *p = new int[10];
    12
    

    释放动态分配的数组存储区时,可使用delete运算符。

    delete []指针变量名;
    delete p;
    12
    
  • new 可在为简单变量分配空间的同时,进行初始化

    指针变量名 = new 类型名(初值);
    int *p;
    p = new int(99);
    ···
    delete p;
    

(10)引用

引用reference)是C++对C的一个重要扩充。变量的引用就是变量的别名,因此引用又称别名

真实的数据类型 &引用名 = 已定义的变量名

引用与其所代表的变量共享同一内存单元,系统并不为引用另外分配存储空间。实际上,编译系统使引用和其代表的变量具有相同的地址。

  • 引用并不是一种独立的数据类型,它必须与某一种类型的变量相联系。在声明引用时,必须立即对它进行初始化,不能声明完成后再赋值。

  • 为引用提供的初始值,可以是一个变量或者另一个引用。

  • 引用的类型必须和其所对应的变量的类型相同

  • 对引用的操作和对引用对应的变量的操作是完全等价的

  • 不允许建立void类型的引用

  • 不能建立引用的数组

  • 可以用const对引用加以限定,不允许改变该引用的值,但是它不阻止引用所代表的变量的值。

#include<iostream>
using namespace std;
int main() {int a = 8;int& ref_a = a;ref_a++;cout << a << endl;//9
}
//上面代码输出a和ref_a的值相同,地址也相同。

引用就是指针的语法糖(syntax sugar)
我们为什么要使用引用呢?我们干嘛要起个别名而不直接用真名呢?
假设我们想通过调用一个函数来实现一个整型变量的自增,有下面3种传递方式:
值传递:形参的改变无法改变实参的值

void fun(int x) {x++;
}
int main() {int a = 8;fun(a);cout << a << endl;//8
}

地址传递:形参的改变可以改变实参的值

void fun(int* x) {(*x)++;//不加括号就会先自增再解引用
}
int main() {int a = 8;fun(&a);cout << a << endl;//9
}

引用传递:形参的改变可以改变实参的值

void fun(int& x) {x++;
}
int main() {int a = 8;fun(a);cout << a << endl;//9
}

是不是比使用指针更简洁些呢

那么,可不可以给引用取别名呢?答案是可以的

int a = 8;
int& a1 = a;
int& a2 = a1;//给引用取别名(引用的嵌套)
int& a3 = a;//同一个对象或变量可以取多个别名

引用和指针的区别

  • 指针是另一个变量,而引用是自己本身,指针会占用额外存储空间,但引用不会占用额外存储空间,也就是说别名和真名是同一个东西,共享同一块内存。
  • 指针可以不用初始化赋值,但是引用必须初始化赋值
  • 指针可以有多级指针,但是引用没有多级引用
  • 指针可以改变指向,但是引用不能改变其所指代的变量或对象
  • 指针是间接访问,引用是直接访问

另外,可以将引用的地址赋值给一个指针,此时指针指向的是原来的变量。

引用作为函数参数、使用引用返回函数值

#include <iostream>
using namespace std;void swap(int &a, int &b)
{int t = a;a = b;b = t;
}int a[] = {1, 3, 5, 7, 9};int& index(int i)
{return a[i];
}int main() 
{int a = 5, b = 10;//交换数字a和bswap(a, b);cout << "a = " << a << " b = " << b << endl;cout << index(2) << endl;   //等价于输出元素a[2]的值index(2) = 100;             //等价于将a[2]的值赋为100;cout << index(2) << endl;return 0;
}

关于指针的更多内容:【C语言】指针

C++的一些标准(兼容旧标准)

1.以初始化列表的方式赋值

int c{2};
int d{(int)3.3};
int arr1[6]{1,2,3};

2.空指针

int *p=NULL;//旧标准
int *p1=nullptr;//新标准

3.自动类型

auto x=10.6;//根据初始化赋值的类型决定变量的类型

4.decltype的使用:可以理解为 复制类型

int n=123;
decltype(n) m=100;//定义一个和变量n一样类型的变量m
decltype((n)) k=n;//给变量n取一个别名k,类似于引用 int& k=n;
123

5.给数据类型取别名

typedef int HP;//旧
using MP = int;//新
typedef void(*pFun)();//旧
using PFun = void(*)();//新
typedef char str[10];//旧
using Str = char[10];//新
123456

6.新的for循环语法规则

#include<iostream>
int main() {int arr2[10] = { 1,2,3,4,5,6,7,8,9,0 };for (int i = 0; i < 10; i++) {std::cout << arr2[i] << '\t';}std::cout<<std::endl;//新for (auto i : arr2) {std::cout << i << '\t';}
}

这个方法只能用来遍历数组或者容器,i所代表的是里面存储的数据元素。指针不能这样遍历。


好啦,下面我们就进入C++的系统学习吧!(笔者会陆续更新哦)

三大特点:

①封装——类和对象

②继承与派生

③多态性与虚函数

运算符重载

函数模版与类模版

C++的输入和输出

异常处理和命名空间

STL标准模板库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/887647.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【FPGA开发】Vivado自定义封装IP核,绑定总线

支持单个文件的封装、整个工程的封装&#xff0c;这里用单个文件举例。 在文件工程目录下&#xff0c;自建一个文件夹&#xff0c;里面放上需要封装的verilog文件。 选择第三个&#xff0c;指定路径封装&#xff0c;找到文件所在目录 取个名&#xff0c;选择封装IP的路径 会…

CA系统(file.h---申请认证的处理)

#pragma once #ifndef FILEMANAGER_H #define FILEMANAGER_H #include <string> namespace F_ile {// 读取文件&#xff0c;返回文件内容bool readFilename(const std::string& filePath);bool readFilePubilcpath(const std::string& filePath);bool getNameFro…

前端-Git

一.基本概念 Git版本控制系统时一个分布式系统&#xff0c;是用来保存工程源代码历史状态的命令行工具 简单来说Git的作用就是版本管理工具。 Git的应用场景&#xff1a;多人开发管理代码&#xff1b;异地开发&#xff0c;版本管理&#xff0c;版本回滚。 Git 的三个区域&a…

深入浅出摸透AIGC文生图产品SD(Stable Diffusion)

hihi,朋友们,时隔半年(24年11月),终于能腾出时间唠一唠SD了🤣,真怕再不唠一唠,就轮不到SD了,技术更新换代是在是太快! 朋友们,最近(24年2月)是真的没时间整理笔记,每天都在疯狂的学习Stable Diffusion和WebUI & ComfyUI,工作实在有点忙,实践期间在飞书上…

HCIP——堆叠技术实验配置

目录 一、堆叠的理论知识 二、堆叠技术实验配置 三、总结 一、堆叠的理论知识 1.1堆叠概述&#xff1a; 是指将两台交换机通过堆叠线缆连接在一起&#xff0c;从逻辑上变成一台交换设备&#xff0c;作为一个整体参与数据的转发。 1.2堆叠的基本概念 堆叠系统中所有的单台…

快速上手:如何开发一个实用的 Edge 插件

在日常浏览网页时&#xff0c;背景图片能够显著提升网页的视觉体验。如果你也想为自己的浏览器页面添加个性化背景图片&#xff0c;并希望背景图片设置能够持久保存&#xff0c;本文将介绍如何通过开发一个自定义Edge插件来实现这一功能。我们将涵盖保存背景设置到插件选项页&a…

介绍一下atol(arr);(c基础)

hi , I am 36 适合对象c语言初学者 atol(arr)&#xff1b;是返回整数(long型)&#xff0c;整数是arr数组中字符中数字 格式 #include<stdio.h> atol(arr); 返回值arr数组中的数字 未改变arr数组 #include<stdio.h> //atol(arr); 返 <stdlib> int main…

Python的排序算法

一、算法 1.1 算法概念 算法就是计算机解决问题的方法或者步骤 程序 数据结构 算法 1.2 算法的特性 1】确定性&#xff1a; 算法的每条语句具有明确的意思&#xff0c;不能模棱两可 2】有穷性&#xff1a;在执行一定的时间后&#xff0c;能自动结束算法 3】输入&#…

npm install -g@vue/cli报错解决:npm error code ENOENT npm error syscall open

这里写目录标题 报错信息1解决方案 报错信息2解决方案 报错信息1 使用npm install -gvue/cli时&#xff0c;发生报错&#xff0c;报错图片如下&#xff1a; 根据报错信息可以知道&#xff0c;缺少package.json文件。 解决方案 缺什么补什么&#xff0c;这里我们使用命令npm…

在windows操作系统上,用git与github账户连接

一、环境准备 1.1 git软件 1.2 github账号 1.3 创建一个项目目录&#xff0c;比如 D:\project\gitproject 二、开始操作 1. 进入项目目录下&#xff0c;右键&#xff0c;如图&#xff0c;打开git bash命令行 2. 在命令行输入以下三个命令 $ git config --global user.name &quo…

视频监控实现画面缩放功能

文章目录 概要一、功能说明二、核心实现代码三、技术细节 概要 在视频监控系统中&#xff0c;经常需要查看视频画面中的细节。通过实现区域放大、滚轮缩放和拖拽平移等功能&#xff0c;可以让用户更方便地观察视频细节。本文介绍如何在 Windows 系统下实现这些交互功能。 一、…

鸿蒙本地模拟器 模拟TCP服务端的过程

鸿蒙模拟器模拟TCP服务端的过程涉及几个关键步骤&#xff0c;主要包括创建TCPSocketServer实例、绑定IP地址和端口、监听连接请求、接收和发送数据以及处理连接事件。以下是详细的模拟过程&#xff1a; **1.创建TCPSocketServer实例&#xff1a;**首先&#xff0c;需要导入鸿蒙…

Three.js 和其他 WebGL 库 对比

在WebGL开发中&#xff0c;Three.js是一个非常流行的库&#xff0c;它简化了3D图形的创建和渲染过程。然而&#xff0c;市场上还有许多其他的WebGL库&#xff0c;如 Babylon.js、PlayCanvas、PIXI.js 和 Cesium&#xff0c;它们也有各自的特点和优势。本文将对Three.js 与这些常…

【04】MySQL数据库和数据表的基本操作详解与实例

文章目录 一、连接MySQL服务器二、数据库的基本操作2.1数据库的基本操作1. 创建数据库2. 选择数据库3. 删除数据库4.查询所有数据库5.修改数据库的字符集 2.2 数据表的基本操作1. 创建数据表2. 查看数据表结构3. 删除数据表4. 修改数据表5. 插入数据6. 查询数据7. 更新数据8. 删…

CTF-Hub SQL 报错注入(纯手动注入)

​ 当输入1时&#xff0c;发现只有查询正确&#xff0c;基本上可以判断出没有回显 开始注入(工具hackerBar) 题目是报错注入&#xff0c;方向就比较明显&#xff0c;大致说一下用到的函数和原理。 常见报错注入函数&#xff1a; 通过 floor() 报错注入通过 extractValue() …

2024 阿里云的Debian12.8,安装mariadb【图文讲解】

目录 一、安装 MariaDB Server 二、登录到MariaDB&#xff0c;记得输入密码&#xff08;注意&#xff1a;密码非明文&#xff0c;只管输入&#xff0c;完成以后回车&#xff09; 三、创建用户 root&#xff0c;并允许从任何主机连接 四、授予用户访问权限 五、刷新权限 六、…

新用户引导库-driverjs

一个比好用的新用户引导的库 driverjs 在做这个功能时&#xff0c;首先要确定目标是什么样子的&#xff0c; 如果只是随意点击下一步下一步&#xff0c;那我感觉可能用图片轮播图的方式会快一点&#xff0c;更容易解决且方便&#xff0c;想要什么步骤 只需要更改图片就好&…

鸿蒙保存读取沙盒文件

鸿蒙保存读取沙盒文件 参考文件 有些时候需要保存并读取沙盒环境的文件。这样做保存一些临时文件&#xff0c;确保发送网络之前数据不会丢失&#xff0c;或者存储一些只需要在本地使用的数据等等。本文介绍一下相关的操作方式。 获取文件路径 想要保存或者读取文件&#xf…

八、利用CSS制作导航栏菜单的习题

题目一&#xff1a; 利用CSS技术&#xff0c;结合链接和样表&#xff0c;设计并实现“ 山水之间 ”页面。 运行效果&#xff1a; 代码 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>山水之间</title>&l…

ML 系列:第 31 节— 机器学习中的协方差和相关性

文章目录 一、说明二、协方差和相关性2.1 协方差的概念2.1 相关 三、有关关联的高级主题 &#xff08;有关详细信息&#xff09;3.1 相关性和独立性3.2 零相关性和依赖性示例 四、相关性和因果关系五、结论 一、说明 协方差量化了两个随机变量协同变化的程度。当一个变量的较高…