当前位置: 首页 > news >正文

基于C语言基础对C++的进一步学习_C和C++编程范式、C与C++对比的一些补充知识、C++中的命名空间、文件分层

0、前言:

  • 因为之前已经有C的基础概念,那么对于C++的学习最好是对比着学,才能高效地掌握C++基础。
  • C++ 是从 C 语言发展而来的,保留了 C 的核心语法和底层操作能力,同时引入了面向对象编程(Object-Oriented Programming:OOP)、泛型编程(模板)、异常处理等高级特性。

1、编程范式:

  • C语言是纯过程式编程(Procedure-Oriented Programming:POP),不支持类、继承、多态等面向对象的特性。C++既支持过程式、也支持面向对象和泛型编程(模板)。两种语言的代码基本结构如下:
// C语言基本结构
#include<stdio.h>
// 其他函数声明
int main()
{// 主函数体
}// C++基本结构
#include<iostream>
using namespace std;  // 使用命名空间std
// 其他函数声明
int main(){// 主函数体
}
  • 面向过程开发的最基本单位是函数,面向对象的开发的最基本单位是类;C 语言是面向过程编程,其 I/O 库设计为一系列全局函数,通过 stdio.h 声明这些函数;C++ 是面向对象编程的扩展,其 I/O 库基于 “流(Stream)” 的概念设计,通过类和对象实现;

2、C与C++对比的一些补充知识:

  • 函数原型也叫函数声明。【c和c++共有的规则】
  • 类和结构体名称首字母大写。【c和c++共有的规则】
  • 类和结构体最后定义完,花括号后面加分号,函数定义完,花括号后面不用加分号。【c和c++共有的规则】
  • 不论是c还是c++,它们的函数传参中都可以分为,值传递和地址传递两种方式,其中地址传参有两种方式,一种就是指针传递,一种就是引用传递,只要是地址传参,都会改变实参的值。【c和c++共有的规则】
  • 函数的默认参数(C++特有):C 语言不支持函数的默认参数,而C++ 支持函数的默认参数。定义函数的时候,形参可以有默认值。调用的时候,如果有实参就调用实参,如果没有实参,就调用默认值;一般默认参数给到声明,但是不能给声明和定义中都给,都给就会出现重定义错误;
  • 内联函数(理解作用):内联函数就是代码片段的快捷方式,不需要像一般函数一样跳转执行,内联函数优点就是执行速度快,没有额外的调用开销,适合简短且常用的函数,使用内联函数的代价是会增加代码体积,使用方式和正常函数一样,就是在定义的时候在函数前面加“inline”,如果函数定义和函数声明是分开的话,inline必须加在定义位置,声明位置可加可不加。【c和c++都支持内联函数】
#include<iostream>
using namespace std;int add(int a, int b);
int main() {cout << add(10,20);return 0;
}
inline int add(int a, int b) // 内联函数的关键是在定义处添加inline关键字
{return a + b;
}
  • ★函数重载(C++特有):用一个函数实现多个功能(要么形参的类型不一样、要么形参的个数不一样),C语言中不支持函数重载,只有C++语言(后缀是.cpp的文件)才支持。函数重载的要求是:参数列表(参数类型、个数或顺序)不同。
#include <iostream>
using namespace std;// 1. 两个整数相加
int add(int a, int b) {cout << "整数相加: ";return a + b;
}// 2. 两个小数相加(参数类型不同)
double add(double a, double b) {cout << "小数相加: ";return a + b;
}// 3. 三个整数相加(参数个数不同)
int add(int a, int b, int c) {cout << "三个整数相加: ";return a + b + c;
}// 函数1:先接收整数,再接收字符串
void printInfo(int age, string name) {cout << "姓名: " << name << ", 年龄: " << age << endl;
}// 函数2:先接收字符串,再接收整数(参数顺序不同)
void printInfo(string name, int age) {cout << "年龄: " << age << ", 姓名: " << name << endl;
}int main() {cout << add(3, 5) << endl;         // 调用第一个add函数cout << add(2.5, 3.8) << endl;     // 调用第二个add函数cout << add(10, 20, 30) << endl;   // 调用第三个add函数// 调用第一个函数(int在前,string在后)printInfo(25, "张三");// 调用第二个函数(string在前,int在后)printInfo("李四", 30);return 0;
}
  • C++ 中的结构体(struct)与 C 语言中的结构体在调用方式和功能上有明显区别,主要体现在 C++ 对结构体进行了面向对象的扩展。C 语言的结构体仅能包含数据成员(变量),而 C++ 的结构体在此基础上还可以包含成员函数(方法),并且支持访问控制(public/private/protected)、继承等面向对象特性。

    • C中通过:“结构体变量.成员” 访问数据;
    • C++中可直接通过:“对象.成员函数()” 操作数据;
    • C++ 的结构体可以像类一样使用,而 C 语言的结构体仅作为数据的聚合类型存在。
    • C中定义结构体变量:struct 结构体名 变量名;
    • C++中定义结构体变量:结构体名 变量名;

3、C++中的命名空间:

  • 从c++的基本结构中发现,有一句代码,using namespace std; 如果没有这句代码,后面代码中使用的cin或者cout就会报错,这是什么原因?
    • 这是因为 cin、cout 这些输入输出对象并不在 “全局命名空间” 中,而是定义在 C++ 标准库的 std 命名空间(namespace)里。如果没有 using namespace std;,就需要显式声明它们所属的命名空间(std::cin >> a;),否则编译器会找不到这些对象,从而报错。
    • 在 C++ 中,“ :: ”是作用域解析运算符
    • 通过上面的问题引出了命名空间的概念;
  • C++ 中命名空间的使用主要通过关键字“namespace”,可以把命名空间理解成 “文件夹”,用来分类存放代码中的变量、函数、类等,避免名字冲突。例如,你有两个文件都叫 “笔记.txt”,直接放在一起会混乱,但分别放在 “工作” 和 “生活” 两个文件夹里就清晰了 —— 命名空间就相当于这些文件夹。在C++语言中,命名空间就是为了解决命名重复的问题。

全名访问:命名空间名::内容(最安全)
打开整个命名空间:using namespace 名字;(方便但谨慎使用)
单独导出:using 命名空间名::内容;(折中方案)

#include<iostream>
using namespace std;
//定义命名空间
namespace a {void fun() {cout << "fun_a" << endl;}
}
// 给命名空间起别名
namespace b = a;
// 嵌套命名空间
namespace c {void fun() {cout << "fun_c" << endl;}namespace d{void fun() {cout << "fun_d" << endl;}}
}
// 在命名空间之外定义函数
namespace e {void fun();
}
void e::fun() {cout << "fun_e" << endl;
}
// 使用了命名空间声明之后,就可以不用在每次调用的时候再写“命名空间名::”
using namespace e;
int main() {// 调用命名空间a::fun();b::fun();c::fun();c::d::fun();e::fun();/*fun_afun_afun_cfun_dfun_e*/fun(); //fun_ereturn 0;
}
  • 命名空间多用于协助开发的时候。

4、文件分层:

  • C 语言通过 “头文件(.h)+ 源文件(.c)” 的分离 和 目录结构规划 来模拟分层,本质是按功能模块拆分代码
    • 头文件(.h):存放函数声明、宏定义、结构体 / 枚举类型定义等 “接口”,相当于模块的 “对外说明”。
    • 源文件(.c):存放函数实现、静态变量等 “内部逻辑”,相当于模块的 “具体实现”。
  • C++ 继承了 C 语言的 “头文件 + 源文件” 机制,同时增加了命名空间(namespace) 来强化逻辑分层,实现更灵活的代码组织:
  • 命名空间解决了不同文件中同名函数 / 类的冲突问题,让文件分层更灵活(同一命名空间的代码可分散在多个文件,不同命名空间的代码可放在同一文件)。
  • 注意:在写头文件的时候,为了防止头文件被重复包含(例如定义了3个头文件a.h、b.h、c.h,b和c中都调用了a,然后在主程序main.c中都调用了b和c,那么对于a中被调用的数据,在main中就是重复定义),最好是在每个头文件当中加上头文件保护符: #ifndef 头文件名大写_H、#define 头文件名大写_H、#endif;
  • 案例:如果需要设置三个头文件,分别是Point.h、Circle.h、Rectangle.h,分别存放坐标结构体,圆的结构体(圆的相关函数声明)、矩形结构体(矩形的相关函数声明)。然后在function.cpp文件中写上圆的相关函数和矩形的相关函数,最后在主程序中调用。
    在这里插入图片描述
// Circle.h
#ifndef CIRCLE_H
#define CIRCLE_H#include"Point.h"struct Circle {Point point;double r;
};double zhou_chang(Circle r);
double mian_ji(Circle r);#endif // !CIRCLE_H
// Rectangle.h
#ifndef RECTANGLE_H
#define RECTANGLE_H#include"Point.h"struct Rectangle {Circle Point;double lang;double kuan;
};double zhou_chang(Rectangle b);
double mian_ji(Rectangle b);#endif // !RECTANGLE_H
// Point.h
#ifndef POINT_H
#define POINT_Hstruct Point {int x;int y;
};
#endif // !POINT_H
// function.cpp
#include<iostream>
#include"Circle.h"
#include"Rectangle.h"//using namespace std;// 矩形
double zhou_chang(Rectangle b) {double zc = 2 * (b.lang + b.kuan);return zc;
}
double mian_ji(Rectangle b) {double mj = b.lang * b.kuan;return mj;
}// 圆
double zhou_chang(Circle a) {double zc = 2 * 3.14 * (a.r);return zc;
}
double mian_ji(Circle a) {double mj = 3.14 * (a.r) * (a.r);return mj;
}
// main.cpp
#include<iostream>
#include"Circle.h"
#include"Rectangle.h"using namespace std;int main() {// 结构体变量初始化Circle a = { {3,4},3};Rectangle b = { {4,5},3,4 };// 调用cout << "a周长:" << zhou_chang(a) << endl;cout << "a面积:" << mian_ji(a) << endl;cout << "b周长:" << zhou_chang(b) << endl;cout << "b面积:" << mian_ji(b) << endl;
}

5、类:

  • 在说明类之前,先讲讲类的由来,c是面向过程的编程语言,其中基本单位是函数,c++既可以面向过程编程,也可以面向对象编程,在面向对象编程时,基本单位是类。
  • 类的定义:举个例子比如你要描述“手机”,它有一些属性(特征):品牌、颜色、内存大小、电量;它的功能(行为):打电话、发短信、拍照;在 C++ 中,类(Class)就是对一类事物的 “模板”“设计图”,它定义了某类事物共同的属性和功能。而我们实际使用的每一部具体手机,就是这个类的 “对象”(实例)
  • 使用类的方式:定义类(属性、功能)、创建对象、访问属性、调用功能;注意:在定义属性和功能的时候有三个关键字描述类当中成员(属性、功能)的权限(private是私有类,类外不可以访问、protected类外不可以访问,子类可以访问父类、public类内和类外都可以访问);需要注意,如果是写在类当中的函数,是不需要把类当中的属性作为形参传递的,这体现了类的封装性;下面是一个定义类的例子:
#include <iostream>
using namespace std;class Rect
{// 设定两个私有的属性,矩形的长和宽,属性名的命名规范:m_类型缩写_属性(首字母大写其他字母小写)
private: // 私有权限int m_nLength; int m_nWidth;
public: // 公有权限// 方法实际上就是声明在类中的函数int getLength();int getWidth();void setLength(int len);void setWidth(int wid);int getArea();int getPerimeter();
};
// 在类外定义方法
// 方法类型 类名::方法名(){函数体}
int Rect::getLength()
{return m_nLength;
}int Rect::getWidth()
{return m_nWidth;
}int Rect::getArea()
{return m_nLength * m_nWidth;
}int Rect::getPerimeter()
{return 2 * (m_nLength + m_nWidth);
}
void Rect::setLength(int len)
{m_nLength = len;
}
void Rect::setWidth(int wid)
{m_nWidth = wid;
}int main()
{// 创建一个对象// 类名 对象名;Rect r1;r1.setLength(100);r1.setWidth(50);cout << r1.getArea() << endl;return 0;
}

总结:

  • 通过C和C++对比着学习,可以发现,C++本质就是对C的扩展,扩展了C不能面向对象编程的问题。C++的这一拓展也导致其编程范式和一些数据结构的书写规范有了区别,比如结构体在c中的定义和书写是一种方式,在C++中就更偏向于类的方式来书写结构体了。
  • 还有就是在给类定义时如何把基本的结构写清楚,要知道在类中定义功能(函数)的时候,如果需要把属性作为形参传入,可以不用写形参,直接在功能当中使用就可以了,这体现了类的封装性。
  • 在进行文件分层时,要把每个头文件中要写上头文件保护符
http://www.dtcms.com/a/329216.html

相关文章:

  • Java Redis基础入门:快速上手指南
  • 广东省省考备考(第七十五天8.13)——判断推理(图形推理题型总结)
  • flex布局之设置主轴上的子元素排列方式一
  • 机器学习之词向量转换
  • 【H5】禁止IOS、安卓端长按的一些默认操作
  • ios添加ic卡如何操作?
  • 8.12 数据分析(1)
  • mac 安卓模拟器 blueStacks
  • windows10的vs2019编译openssl静态库备忘
  • 随想记-excel报表美化
  • unity_MCP
  • 类和对象(中下)
  • 《Linux基础知识-4》
  • Kubernetes-03:Service
  • LeetCode——456. 132 模式
  • 6 .循环-for
  • 高级项目——基于FPGA的串行FIR滤波器
  • Rust面试题及详细答案120道(01-10)-- 基础语法与数据类型
  • 日志数据链路的 “搬运工”:Flume 分布式采集的组件分工与原理
  • React常见的Hooks
  • 低成本扩展方案:S7-200SMART作为S7-1500分布式IO从站的上位机配置指南
  • 第三天-在DBC中创建一个Signal Group信号组
  • MySQL新增字段与Java实体不同步:常见问题排查与高效解决方案
  • 流处理 or 批处理?大数据架构还需要流批一体吗?
  • wangeditor v4修改缩进并清除粘贴文档带入的格式
  • MySQL极简安装挑战:从依赖管理到高效部署
  • MySQL数据线上扩容方案
  • npm安装时一直卡住的解决方法
  • Grayscale® 推出 Walrus 和 DeepBook 信托产品
  • 图像分类-动手学计算机视觉10