【第一节】从C语言到C++

目录

一、面向对象编程

1.早期概念

2.发展与普及

3. 现代发展

二、从C语言到C++

1.关于堆内存的使用

2.关于函数重载

3.关于默认参数

4.引用

5.引用参数

6.作用域符号

三、C++的输入输出机制


一、面向对象编程

        面向对象编程(Object-Oriented Programming,简称OOP)是一种计算机编程范式,它使用“对象”来设计应用程序和计算机程序。这种编程范式强调数据和操作数据的函数(方法)的封装,以及对象之间的交互。面向对象编程的由来和发展可以追溯到20世纪60年代,以下是其主要的发展历程:

1.早期概念

  • Simula语言(1960年代):被认为是第一个引入面向对象概念的编程语言。Simula引入了类(class)和对象(object)的概念,以及继承和动态绑定等特性。

  • Smalltalk语言(1970年代):由Alan Kay等人开发,是第一个完全基于面向对象概念的编程语言。Smalltalk对后来的面向对象编程语言产生了深远影响,它定义了许多现代OOP语言的特性,如消息传递、类和对象、继承等。

2.发展与普及

  • C++语言(1980年代):由Bjarne Stroustrup开发,最初称为“C with Classes”。C++在C语言的基础上增加了类和对象的概念,支持面向对象编程,同时也保持了对C语言的兼容性。C++的成功使得面向对象编程开始广泛流行。

  • Objective-C语言(1980年代):由Brad Cox和Tom Love开发,是另一种支持面向对象编程的语言,后来被苹果公司用于开发Mac OS X和iOS应用程序。

  • Java语言(1990年代):由Sun Microsystems的James Gosling等人开发。Java是一种完全面向对象的编程语言,它的跨平台特性(通过Java虚拟机实现)和简单性使其迅速成为主流编程语言之一。

  • Python、Ruby等语言(1990年代至今):这些语言都支持面向对象编程,并且各自以简洁的语法和强大的功能吸引了大量开发者。

3. 现代发展

  • 多范式编程语言:现代编程语言如C#、JavaScript、Swift等,虽然支持面向对象编程,但也支持其他编程范式,如函数式编程。

  • 设计模式和框架:随着面向对象编程的普及,出现了许多设计模式(如单例模式、观察者模式等)和框架(如Spring、Hibernate等),这些都极大地丰富了面向对象编程的实践。

        面向对象编程的核心概念包括封装、继承和多态,这些概念使得代码更加模块化、可重用和易于维护。随着技术的发展,面向对象编程继续在软件开发领域扮演着重要角色。

 

二、从C语言到C++

        C++是C的扩展,C是C++的子集,C++包括C的全部特征、属性和优点。同时,增加了对面向对象编程的完全支持。接下来我们先了解C++一些特点,帮助大家更好的从C过度到C++的基本使用。

1.关于堆内存的使用

        C++中申请堆空间用的是new与delete运算符,这两个类似于c语言中的malloc与free函数。
new使用方式如下所示:
语法:
指针变量 = new 数据类型:
指针变量 = new 数据类型[长度n];
例如:
int *p; pnew int;
char *pStr = new char[50];

delete使用方式如下:
语法:
delete 指针变量:
delete[]指针变量;

例如:
delete p;
delete [] pStr;//对于数组

代码示例:

#include <iostream>

using namespace std;
int main() {
    int* p = new int(33);//分配一个整数空间4字节,圆括号代表初始化值
    cout << *p << endl;
    int* p2 = new int[10];//分配连续的10个整数空间40字节
    delete p;
    delete[] p2;
    return 0;
}

        我们可以把new和delete对比着malloc与free来学习:
1)从示例中可以看出使用new申请空间并不是以字节为单位的,而是以数据类型,从而
也无需强制转换。
2)要申请多个数据,需要使用了中括号,释放这块内存的时候也需要中括号。
3)注意中括号和圆括号的差别,圆括号是初始化,中括号是申请多个的意思。

 

2.关于函数重载

        相同的作用域,如果两个函数名称相同,面参数不同,我们把它们称为函数重载,函数
重载又称为函数的多态性。请一定注意那个前提:相同的作用域、相同的作用域,相同的作用域。

以下几种方式会构成函数重载

形参数量不同
形参类型不同
形参的顺序不同
形参数量和形参类型都不同

        总而言之,就是参数的不同会构成重载,那么构成了重载有什么用处呢?
如果我们的算法需要支持多个数据类型,比如求两个数的和,想要支持整数,浮点数甚至字符串。
如果没有函数重载实现如下:

int AdditionInt(int numA, int numB) {
    return numA + numB;
}
double AdditionDouble(double numA, int numB) {
    return numA + numB;
}
int AdditionStr(char* pNumA, char* pNumB) {
    int nNumA = 0;
    int nNumB = 0;
    sscanf_s(pNumA, "%d", &nNumA);
    sscanf_s(pNumB, "%d", &nNumB);
    return nNumA + nNumB;
}

        对于函数的使用者而言,需要记住三个功能类似,但是名称不同的函数。而代码写成下面的样子,就可以解决这个问题:

int Addition(int numA, int numB) {
    return numA + numB;
}

double Addition(double numA, int numB) {
    return numA + numB;
}
int Addition(char* pNumA, char* pNumB) {
    int nNumA = 0;
    int nNumB = 0; 
    sscanf_s(pNumA, "%d", &nNumA);
    sscanf_s(pNumB, "%d", &nNumB);
    return nNumA + nNumB;
}

        此代码在C语言中会因为函数重名而编译失败,但在C++中这则是一个典型的重载函数C++会根据传入函数参数的不同进而决定调用哪个函数。有了这个机制,使用者仅仅需要记住一个函数名即可,随意的往里面传递各种数据类型。函数重载的本质,以上的同名函数,在C++看来实际上是不同的函数名称,C++为了支持这种特性,进而提出了名称粉碎/名字改编(name managling)机制,以上面的函数为例,他们的函数名分别不同。根据函数参数的不同,把函数修改成了不同的名字。

3.关于默认参数

        在C++中,还有一个不错的机制,叫做默认参数,函数声明或者定义的时候,可以给形参赋一些默认值,调用函数时,若没有给出实参,则按指定的默认值进行工作。

int Addition(int a, int b, int c = 0, int d = 0, int e = 0) {
    return a + b + c + d + e;
}

        在以上这个例子中,调用函数的时候,可以传递两个参数,也可以传递三个,四个,五传递的参数不足五个的时候,后面的会默认的被传递0。个。需要注意的几个问题:
1)函数没有声明时,在函数定义中指定形参的默认值
2)函数既有定义又有声明时,声明时指定后,定义后就不能再指定默认值
3)当使用了默认参数的同时还使用了重载容易造成二义性

#include<iostream>
using namespace std;

int fun(int a, int b = 5) {
    //声明与定义在一起,直接写默认参数就可以
    return a + b;
}

int fun(int a, int b, int c = 3);//1声明与定义不能同时带默认参数int  //2这里造成了二义性

int main(void) {
    cout << fun(3) << endl;
    cout << fun(3, 4) << endl;
    cout << fun(3, 4, 5) << endl;
    return 0;
}

int fun(int a, int b, int c) {
    return a + b + c;
}

4)默认值的定义必须遵守从右到左的顺序,如果某个形参没有默认值,则它左边的参数就不能有默认值。

void funcl(int a, double b = 4.5, int c = 3);//合法
void funcl(int a = 1, double b, int c = 3);//不合法

函数调用时,实参与形参按从左到右的顺序进行匹配。

 

4.引用

        引用是C++引入的新语言特性,是C++常用的一个重要内容之一,正确、灵活地使用引用,可以使程序简洁、高效。
引用是给一个变量起别名,定义引用的一般格式:
类型 &引用名 = 变量名;
int nSize;
&nNum = nSize;

需要注意的是:
1)由于引用就是变量的一个别名,因此上例中nSize的地址与m的地址是完全一样的;
2)定义引用时一定要初始化,指明该引用变量是谁的别名;
3 )引用一经初始化不能再引用其他对象。

示例代码:

#include <iostream>
using namespace std;

int main(void) {
    int val = 100;
    //int &refval; //Error,引用必须初始化
    int& refval = val; 
    refval = 200;//将200赋值给refval//实际上改变的是val这个变量
    cout << "val=" << val << endl;
    int val2 = 500;
    refval = val2;//不代表将refval引用至va12这个变量//仅仅只是代表将va12赋值给refval
    cout<< "val="<<val<<endl;
}

5.引用参数

        引用传递方式是在函数定义时在形参前面加上引用运算符"&”
        例如:int swap(int &nNumA, int &nNumB);
        按值传递方式容易理解,但形参值的改变不能对实参产生影响,地址传递方式通过形参的改变使相应的实参改变,但是C++的设计者认为这恰巧是C语言程序容易产生错误且难以阅读的原因。
        于是引用在这里发挥了重要的作用,引用作为参数对形参的任何操作都能改变相应的实参的数据,又使函数调用显得方便、自然。

代码示例:

#include <iostream>
using namespace std;

//引用作为参数传递
void swap(int& x, int& y) {
    int temp = x;
    x = y;
    y = temp;
}
int main(void) {
    int a = 5;
    int b = 6;
    swap(a, b);//在函数调用时,引用被初始化x=a,y=b;
    cout<< "a=" << a <<"b=" << b << endl;
    return 0;
}

引用和指针的区别:
引用访问一个变量是直接访问,而指针里面需要保存变量的地址,所以是间接访间
引用是一个变量的别名,本身不单独分配自己的内存空间,它不是一个单独的变量,而指针有自己的内存空间
引用一经初始化不能再引用其它变量,而指针可以(非const指针)
尽可能使用引用,不得已时使用指针。

三种传参方式比较:
值传递:实参要初始化形参要分配空间,将实参内容拷贝到形参
指针传递:传递的是地址,能够间接修改函数外部的变量,其本质仍是值传递。
引用传递:实参初始化形参的时候不分配空间,而是形参实参融为一体,修改了形参就是改变了实参。

 

6.作用域符号

在C++中,双冒号::被称为作用域解析运算符(Scope Resolution Operator)。它主要用于以下几个方面:

1. 访问全局变量:当局部变量与全局变量同名时,可以使用::来访问全局变量。例如:

int x = 10; // 全局变量
void someFunction() {
    int x = 20; // 局部变量
    std::cout << x << std::endl; // 输出局部变量x的值,即20
    std::cout << ::x << std::endl; // 输出全局变量x的值,即10
}

2. 访问类成员:在类的外部定义成员函数时,需要使用::来指定该函数属于哪个类。例如:

class MyClass {
public:
    void myFunction();
};

void MyClass::myFunction() {
    // 函数实现
}

3. 访问命名空间成员:当一个命名空间中的名称与另一个命名空间或全局作用域中的名称冲突时,可以使用::来指定访问哪个命名空间中的成员。例如:

namespace MyNamespace {
    int x = 10;
}

int x = 20;

int main() {
    std::cout << x << std::endl; // 输出全局变量x的值,即20
    std::cout << MyNamespace::x << std::endl; // 输出MyNamespace中的x的值,即10
    return 0;
}

        作用域解析运算符::在C++中是一个非常关键的工具,它帮助程序员清晰地管理和访问不同作用域中的变量和函数,有效地解决了命名冲突的问题。

三、C++的输入输出机制

        I/0流是指输入输出的一系列数据流,输出使用插入操作符“<<”向cout 输出流中插入字符。
在使用 cout 和 cin的时候,需要包含 iostream 这个头文件,并且使用 std 这个命名空间。如下所示:

#include <iostream>
using namespace std;

int main() {
    cout << "this is a program";
    return 0;
}

输入使用抽取操作符“>>”从cin输入流中抽取字符

#include <iostream>
using namespace std;

int main() {
    int myage;
    cin >> myage;
    int i; float f; long l; 
    cin >> i >> f >> l; 
    return 0;
}

C++的输出能够控制输出的数据格式,常用格式如下:

控制符描述
dec按10进制输出
hex按16进制输出
oct按8进制输出
setfi1l(c)设填充字符为c
setprecision(n)设置显示小数精度为n位
setw(n)设域宽为n个子符
setiosflags(ios::fixed)小数方式表示
setiosflags(ios::scientific)指数表示
setiosflags(ios::left)左对齐
setiosflags(ios::right)右对齐

输出宽度示例
cout<<setw(8)<<10<<endl;

若数值10和20均按照宽度8输出
cout<<setw(8)<<10<<setw(8)<<20<<endl;

如果一个值的位数大于setw(n)确定的宽度位数,则按原宽度输出,例如
float amount=4.53671;
cout<<setw(4)<<amount<<endl ;

输出八进制,十六进制和十进制数示例:

#include <iostream>
#include <iomanip>
#include<stdlib.h>
using std::wcout;
using std::endl;
using std::setiosflags;
using std::ios; 

int main() {
    int number = 1001;
    wcout << L"Decimal:"<< std::dec << number << endl \
        << L"Hexadecimal :" << std::hex << number << endl \
        << L"Octal:" << L"Hexadecimal :" << std::hex \
        << std::oct << number << endl \
        << setiosflags(ios::uppercase) << number << endl; 
    system("pause");
    return 0;
}

控制左右对齐输出,默认情况下,I/0流以右对齐格式显示。

#include <iostream>
#include <iomanip>#include<stdlib.h>
using std::endl; using std::setiosflags; 
using std::setw; using std::wcout;

int main() {
    wcout << setiosflags(std::ios::left) << setw(5) << 1 << setw(5) << 2 << setw(5) << 3 << endl; 
    wcout << setiosflags(std::ios::right) << setw(5) << 1 << setw(5) << 2 << setw(5) << 3 << endl; 
    system("pause");
    return 0;
}

以上是 C++提供的输入输出方式,使用printf/scanf 依然也是可以的。

如下输出打印一个菱形图案:

4ff54b3d79b14d0e8eeb48bf05ab85bd.png

#include <iostream>
#include <iomanip>
#include <stdlib.h>
using std::wcout; 
using std::endl;
using std::setfill; 
using std::setw; 

int main() {
    for (int i = 0; i < 7; i++) {
        if (i < 4) {
            wcout << setfill(L' ') << setw(4 - i) << L' ';
            wcout << setfill(L'*') << setw(i * 2 + 1) << L'*' << endl;
        }
        else {
            wcout << setfill(L' ') << setw(i - 2) << L' ';
            wcout << setfill(L'*') << setw(i - (i - 4) * 3 + 1) << L'*' << endl;
        }
    }
    system("pause");
    return 0;
}

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Midjourney进阶必看 | 垫图效果的必备技能

还在纠结Midjourney垫图效果不佳&#xff1f;快看看是不是这5点没有做好&#xff01; 前言一、内容形式要一致二、用文本描述强调画面内容三、尝试不同的--iw参数四、用--no参数去除隐藏干扰项五、记得多生成几次 总结 前言 图像提示词&#xff0c;也就是垫图&#xff0c;是Mi…

Verilog实战学习到RiscV - 1 : Yosys 综合

Yosys 综合 实例 一般 FPGA IDE 的第一步都是RTL 综合&#xff08;Synthesis&#xff09;。之后就能看到数字电路图了。然后可以做RTL 级的仿真模拟。 直接上代码&#xff0c;这里我们看一个简单的加法器来学习。 module adder(input [7:0] a,input [7:0] b, input …

Java | Leetcode Java题解之第103题二叉树的锯齿形层序遍历

题目&#xff1a; 题解&#xff1a; class Solution {public List<List<Integer>> zigzagLevelOrder(TreeNode root) {List<List<Integer>> ans new LinkedList<List<Integer>>();if (root null) {return ans;}Queue<TreeNode> n…

el-tabs中的下拉框被覆盖解决方法

解决方法&#xff1a; ::v-deep .el-tabs__content{// overflow:hidden 会导致 分页下拉框超出部分会被.el-tabs__content隐藏overflow: visible; }

基础—SQL—DML(数据操作语言)修改和删除

一、引言 接着上次博客&#xff0c;这次讲解DML语句中的修改数据和删除数据操作。 二、DML—修改数据 UPDATE 表名 SET 字段名1值1 ,字段名2值2 , ...[ WHERE 条件]; 注意&#xff1a;修改语句的条件可以有&#xff0c;也可以没有。如果没有条件&#xff0c;则会修改整张表的…

MySQL 解决登录报错 - 错误1130- Host xxx is not allowed to connect to this server

1、原因 没有给远程连接权限 2、解决 2.1 打开命令行提示符界面输入命令cd C:\Program Files\MySQL\MySQL Server 8.0\bin\ 2.2 连接 MySQL 数据库 输入命令 mysql -u root -p &#xff0c;然后输入密码 回车登录 2.3 查看当前表中的数据库 show databases;查看当前使用的数…

每天写两道(二)LRU缓存、数组中最大的第k个元素

146.LRU 缓存 . - 力扣&#xff08;LeetCode&#xff09; 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存…

在Anki中按某个字段满足的条件查找笔记

Anki中可以使用deck、tag、card、note、is、prop、added、rated、nid、cid等关键字按照牌组、标签、卡片、卡片类型、状态、属性、添加时间、回答时间、对象id等对卡片进行筛选&#xff0c;但是没有提供按卡片字段进行筛选的关键字&#xff0c;那么&#xff0c;怎么按卡片字段是…

C++ (week5):Linux系统编程3:线程

文章目录 三、线程1.线程的基本概念①线程相关概念②我的理解 2.线程的基本操作 (API)(1)获取线程的标识&#xff1a;pthread_self(2)创建线程&#xff1a;pthread_create()(3)终止线程①pthread_exit()&#xff1a;当前线程终止&#xff0c;子线程主动退出②pthread_cancel()&…

安卓ADB通过WIFI无线连接手机[通过无线安装APK]

安卓ADB通过无线连接手机 本文摘录于&#xff1a;https://www.cnblogs.com/zhuxibo/p/14261117.html只是做学习备份之用&#xff0c;绝无抄袭之意&#xff0c;有疑惑请联系本人&#xff01; 别人给的操作确实可行,我这里实操记录如下: AdministratorpiaoranPC MINGW64 /e/Wor…

大模型部署框架 FastLLM 简要解析

0x0. 前言 本文主要是对FastLLM做了一个简要介绍&#xff0c;展示了一下FastLLM的部署效果。然后以chatglm-6b为例&#xff0c;对FastLLM模型导出的流程进行了解析&#xff0c;接着解析了chatglm-6b模型部分的核心实现。最后还对FastLLM涉及到的优化技巧进行了简单的介绍。 0…

Java 阻塞队列与生产者消费者模型

一、阻塞队列 阻塞队列是⼀种特殊的队列&#xff0c;其也遵守队列 "先进先出" 的原则&#xff1b; 阻塞队列是⼀种线程安全的数据结构&#xff0c;并且具有以下特性&#xff1a; 当队列满的时候&#xff0c;继续入队列就会阻塞&#xff0c;直到有其他线程从队列中…

成都市酷客焕学新媒体科技有限公司:助力品牌打破困境!

在数字化浪潮的推动下&#xff0c;营销策略对品牌的发展愈发关键。成都市酷客焕学新媒体科技有限公司&#xff0c;作为短视频营销领域的佼佼者&#xff0c;凭借其卓越的策略和实力&#xff0c;助力众多品牌在信息海洋中脱颖而出&#xff0c;实现品牌的显著增长。 酷客焕学专注于…

抖音和快手哪个好?来全面了解一下他们的区别!

快手和抖音虽然是短视频领域的两大主流平台&#xff0c;但是两者也存在本质的区别&#xff0c;从产品定位、用户群体到视频风格、变现模式&#xff0c;它们的特征都不一样。 &#xff08;一&#xff09;两个平台核心区别&#xff1a; 1. 核心用户不一样&#xff1a;抖音以1、…

【最优化方法】实验四 约束最优化方法的MATLAB实现

实验的目的和要求&#xff1a;通过本次实验使学生较为熟练使用MATLAB软件&#xff0c;并能利用该软件进行约束最优化方法的计算。 实验内容&#xff1a; &#xff11;、罚函数法的MATLAB实现 &#xff12;、可行方向法的MATLAB实现 学习建议&#xff1a; 本次实验就是要通…

942. 增减字符串匹配 - 力扣

1. 题目 由范围 [0,n] 内所有整数组成的 n 1 个整数的排列序列可以表示为长度为 n 的字符串 s &#xff0c;其中: 如果 perm[i] < perm[i 1] &#xff0c;那么 s[i] I 如果 perm[i] > perm[i 1] &#xff0c;那么 s[i] D 给定一个字符串 s &#xff0c;重构排列 pe…

新能源汽车推行精益生产:绿色动力下的效率革命

在新能源汽车行业迅猛发展的当下&#xff0c;推行精益生产已成为提升竞争力的关键所在。精益生产&#xff0c;作为一种以客户需求为导向、追求流程最优化和浪费最小化的管理理念&#xff0c;正逐步在新能源汽车领域展现出其独特的魅力。 新能源汽车的兴起&#xff0c;不仅代表了…

【云原生】kubernetes中Configmap原理解析与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Python中tkinter入门编程9

在《Python中tkinter编程入门8-CSDN博客》中提到&#xff0c;tkinter中的Canvas表示画布&#xff0c;可以在画布中显示文字和图片。除了以上功能外&#xff0c;还可以在Canvas中添加对鼠标或键盘的响应。 1 为Canvas添加事件响应 可以通过Canvas的bind()方法添加对鼠标或键盘…

深圳比创达电子|EMC与EMI滤波器:电子设备的“电磁防护罩”

在电子科技日新月异的今天&#xff0c;电磁兼容性&#xff08;EMC&#xff09;问题越来越受到工程师和技术人员的关注。其中&#xff0c;电磁干扰&#xff08;EMI&#xff09;和电磁干扰抑制&#xff08;即EMI滤波器&#xff09;是实现良好EMC性能的关键技术之一。 一、EMC与E…