标准C++(二)

news2024/9/23 12:18:31

一、名字空间

什么是名字空间

在C语言中定义的全局变量、函数、结构、联合、枚举、枚举值、宏都在全局作用域下,所以当项目比较庞大时,非常容易造成命名冲突(以模块名作前缀、后缀),所以C++中选择把全局作用域进行拆分成 子作用域进行管理,这些子作用域就是作名字空间。

如何设计名字空间
namespace 空间名 {
    // 子作用域
    在该作用域中定义全局变量、函数、结构、联合、枚举、枚举值...,不会与全局变量中的命名冲突
} // 此处没有分号
如何使用名字空间中的内容
方法1:

直接使用空间中的内容

空间名::标识符;

#include <iostream>
​
int main(int argc,const char* argv[])
{
    std::cout << "我要使用std中的内容" << std::endl;        
    return 0;
}
方法2:

把空间中的部分内容导入到当作用域下,一旦导入之后就可以方便的直接使用

using 空间名::标识符;

#include <iostream>
​
using std::cout;
using std::endl;
​
int main(int argc,const char* argv[])
{
    cout << "我要使用std中的内容" << endl;              
    return 0;
}
方法3:

把空间中的所有内容导入到当前作用域下

using namespace 空间名;

#include <iostream>
​
using namespace std;
​
int main(int argc,const char* argv[])
{
    string str = "string类也定义在std名字空间中";
    cout << str << endl;
    return 0;
}

注意:C++标准库中提供的基础功能的类、对象都定义在std名字空间中,如:cout、cin、string。

空间合并与空间嵌套

1、编译器会把同名的名字空间的内容自动合并,同名的名字空间就是同一个作用域,如果同一个作用域 下有命名冲突编译就会报错。

#include <iostream>
using namespace std;
​
namespace ns {
    int num1 = 1234;
}
​
namespace ns {
    int num2 = 5678;
    int num1 = 6666;
}
​
int main(int argc,const char* argv[])
{
    using namespace ns;
    cout << num1 << " " << num2 << endl;
    return 0;
}

2、名字空间中可以再定义名字空间

#include <iostream>
using namespace std;
​
namespace ns1 
{
    namespace ns2 
    {   
        namespace ns3 
        {
            int num = 123456789;
        }
    }   
}
​
// 嵌套后的名字空间使用起来比较长,可以给内部名字空间取别名
namespace ns123=ns1::ns2::ns3;
​
int main(int argc,const char* argv[])
{
    cout << ns1::ns2::ns3::num << endl;
    cout << ns123::num << endl;
    return 0;
}
匿名名字空间

C++把默认的全局作用域当作一个没有名字的名字空间,也叫匿名名字空间,当全局的标识符被屏蔽,可以使用匿名空间的域限定符来指定全局作用域的标识符。

#include <iostream>
using namespace std;
​
int num = 1234;
int main(int argc,const char* argv[])
{
    int num = 5678;
    cout << num << endl;
    cout << ::num << endl;
    return 0;
}
注意:

工作时尽量不要使用 using namespace 空间名; 这种用法,这就像是把垃圾分类之后,又合并了,如果使用到标识符,一定要 空间名::标识符。

二、面向过程与面向对象

面向过程:

在编程时重点考虑如何解决问题,以及解决问题的具体步骤。

面向对象:

在编程时重点考虑的是"谁"能解决问题(类、结构),以及"它"解决问题时所需要属性(成员变量)和功能(成员函数)。

抽象:

把“解决问题者”当作思考或观察对象,把解决问题所需的具备的属性和功能罗列出来,这个步骤叫作抽象。

封装:

把抽象的结果(问题所需的具体的属性和功能),设置相应访问权限(public/private/protected),按照C++的语法设计成类、结构,该过程叫作封装类,简称封装。

使用封装好的类、结构,实例化出对象(定义结构变量、类变量),通过对象调用相关功能(成员函数)配合相关属性(成员变量)达到解决问题的目的。

继承:

1、在解决一个问题之前,先考虑现有的类是否能解决部分问题,如果有则继承该类,在此基础上进行扩展,以缩短解决问题的时间(代码复用)。

2、在解决一个复杂庞大的问题时,把问题拆分成若干个小问题,每个小问题实现一个类去解决,最后把这若干个类通过继承进行汇总,达到解决问题的目的,这个方式可以降低问题的规模在难度,也方便团队分工、协作。

多态:

语句的多种形态,同样的语句根据环境或参数的不同,有不同的功能,这就叫多态。

多态可以分为:

编译时多态,编译器在编译代码时根据语句的参数、环境不同,能翻译出具有不同功能的二进制指令,例如:调用重载的函数,cin、cout的自动类型识别,模板技术(后续讲解)。

运行时多态,语句只在程序运行时,才能确定执行那种功能,一般指的是类多态,后续再详细讲解。

#include <iostream>
using namespace std;
​
void func1(void)
{
    cout << "我是func1函数" << endl;
}
​
void func2(void)
{
    cout << "我是func2函数" << endl;
}
​
int main()
{
    void (*fp)(void);
    
    int cmd;
    cin >> cmd;
    if(cmd % 2)
        fp = func1;
    else
        fp = func2;
    
    fp();
}

三、类和对象

什么是类

把抽象结果(利用面向对象的思维模式,思考、观察出的结果),使用用C++的语法封装出一种类似结构的自定义数据类型(复合数据类型)。

如何设计类
struct 结构名
{
    成员函数;	// 结构的成员默认访问权限是public
    成员变量;
};

class 类名
{
    成员变量;	// 结构的成员默认访问权限是private
    成员函数;
};

注意:在C++中类的结构除了成员的默认访问权限不同,没有任何区别(大师兄说的)。
访问限制符

使用以下关键字修改结构、类的成员,管理它们的访问权限:

private: 私有的,被它修饰的成员,只能在类的成员函数内使用。
protected: 保护的,被它修饰的成员,只能在类、子类的成员函数内使用。
public: 公开的,被修饰的成员,可以在任何位置使用。
#include <iostream>
using namespace std;

struct Student
{
    void in(void)
    {   
        cout << "请输入学生的学号、姓名、年龄、成绩:"; 
        cin >> id >> name >> age >> score;
    }   
    void out(void)
    {   
        // 学号:10010 姓名:hehe 年龄:18 成绩:100
        cout << "学号:" << id << " 姓名:" << name << " 年龄:" << age << " 成绩:" << score << endl;
    }   
private:
    int id; 
    char name[20];
    short age;
    float score; 
};

class Student
{
    int id; 
    char name[20];
    short age;
    float score;   
public:
    void in(void)
    {   
        cout << "请输入学生的学号、姓名、年龄、成绩:"; 
        cin >> id >> name >> age >> score;
    }   
    void out(void)
    {   
        // 学号:10010 姓名:hehe 年龄:18 成绩:100
        cout << "学号:" << id << " 姓名:" << name << " 年龄:" << age << " 成绩:" << score << endl;
    } 
};

int main(int argc,const char* argv[])
{
    Student stu;
    stu.in();
    stu.out();
    return 0;
}
什么是类对象

使用设计好的类(结构)这种数据类型,定义出的类变量在面向对象编程语言中被称为对象(结构变量),创建类对象的行为也被称为实例化对象。

#include <iostream>
using namespace std;

class Student
{
    int id; 
    char name[20];
    short age;
    float score;
public:
    void in(void)
    {   
        cout << "请输入学生的学号、姓名、年龄、成绩:"; 
        cin >> id >> name >> age >> score;
    }   
    void out(void)
    {   
        // 学号:10010 姓名:hehe 年龄:18 成绩:100
        cout << "学号:" << id << " 姓名:" << name << " 年龄:" << age << " 成绩:" << score << endl;
    }   
};

Student stu; // 在bss内存段上实例化对象
int main(int argc,const char* argv[])
{
    Student stu; // 在stack内存段实例化对象
    Student* stup = new Student; // 在heap内存段实例化对象
}

类的声明与实现分开

如果类的内容不多,一般会选择只定义一个头文件,以类名作为文件名。

#ifndef STUDENT_H
#define STUDENT_H

class 类名
{
    // 定义成员变量
public:
    // 定义成员函数
};

#endif//STUDENT_H

如果类的内容比较多,会选择把类的声明与定义分开,头文件负责类的声明,源文件负责类的实现。

#ifndef STUDENT_H
#define STUDENT_H

class 类名
{
    // 定义成员变量
public:
    // 声明成员函数
    void 函数名(参数列表);
};

#endif//STUDENT_H
#include "student.h"

void 类名::函数名(参数列表)
{
    
}
练习:实现C++版的通讯录。

四、构造函数与析构函数

构造函数
1、什么构造函数

类、结构、联合中的特殊成员函数,与类名、结构名、联合名同的成员函数,没有返回值。

class 类名
{
public:
    类名(参数列表)
    {
        
    }
};
2、何时调用构造函数

当创建类对象时(实例化对象)会自动调用构造函数。

int main(int argc,const char* argv[])
{
    // 调用无参构造
    Student stu;
    Student* stup = new Student;

    // 调用有参构造
    Student stu1(10010,"hehe",'w',18,98);
    Student* stup1 = new Student(10011,"xixi",'m',20,95);
    
    // 调用有参构造,c11语法标准才支持,-std=c++11
    Student stu2 = {10010,"hehe",'w',18,98};
    return 0;
}
3、在构造函数中应该做什么

构造函数负责创建使用对象的环境,一般构造函数中负责:

1、给成员变量初始化

2、给指针成员分配内存

3、从文件、网络、数据库加载数据

4、完成一些准备工作

4、实现构造函数要注意的问题

在创建类对象时,一定会调用构造函数,如果类中没有显式实现构造函数,编译器会自动生成一个无参的什么都不做的构造函数。

如果显式实现了有参构造函数,那么编译器就不会再生成无参构造。

注意:在使用new[] 创建n个对象时,无法保证给所有的类对象都单独提供参数,去调用有参构造,那么必然需要调用无参构造,此时如果没有显式实现无参构造,编译就会出错。

方法1:

class Student
{
public:
    Student() {} // 极简无参构造
};

方法2:

给有参构造函数的所有成员都设置默认形参,当需要调用无参构造时,会自动使用默认参数调用有参构造。

// 无参构造未必无参
class Student
{
	...
public:
	Student(int _id=0,const string& _name="",char _sex='w',short _age=0,float _score=0)
    {
        id = _id;
        name = _name;
        sex = _sex;
        age = _age;
        score = _score;
        cout << "我是有参构造" << endl;
    }
};
5、explicit关键字的作用

如果类中有单参的构造函数,那么它的参数类型数据就能隐藏提升为类对象,如果不使用该功能,可以在单参构造函数的前面加 explicit 关键字,参数类型数据就不能再隐藏提升为类对象。

总结:explicit关键字的作用就是禁止单参构造函数的类型提升功能。

#include <iostream>
using namespace std;

class Test
{
    int num;
public:
    [explicit] Test(int _num)
    {   
        num = _num;
    }    
};

void func(Test t)
{
    cout << "我被调用了" << endl;
}

int main(int argc,const char* argv[])
{
    func(1234);
}

析构函数:
1、什么析构函数

类、结构、联合中的特殊成员函数,在类名、结构名、联合的前面加~,就是析构函数,没有返回也没有参数。

struct Student
{
    int id; 
    string name;
    char sex;
    short age;
    float score;
public:
    Student(void)
    {
        cout << "我是无参构造函数" << endl;
    }
    Student(int _id,const string& _name,char _sex,short _age,float _score)
    {   
        id = _id;
        name = _name;
        sex = _sex;
        age = _age;
        score = _score;
        cout << "我是有参构造" << endl;
    }   
    ~Student(void)
    {   
        cout << "我是析构函数" << endl;
    }   
};
2、在析构函数中应该做什么

析构函数负责对象销毁时的收尾工作,一般构造函数中负责:

1、释放指针成员指向的堆内存

2、往文件中、数据库保存数据

3、何时调用析构函数

1、当类对象离开它所在的作用域时,系统会自动销毁类对象,并自动调用析构函数。

#include <iostream>
using namespace std;

struct Student
{
    int id;
    string name;
    char sex;
    short age;
    float score;
public:
    Student(void)
    {
        cout << "我是无参构造函数" << endl;
    }
    Student(int _id,const string& _name,char _sex,short _age,float _score)
    {
        id = _id;
        name = _name;
        sex = _sex;
        age = _age;
        score = _score;
        cout << "我是有参构造" << endl;
    }
    ~Student(void)
    {
        cout << "我是析构函数" << endl;
    }
};

int main(int argc,const char* argv[])
{
    do{
        // 当创建类对象时,自动调用构造函数,当对象离开它的作用域时,会自动调用析构函数
        Student stu;
    }while(0);
    cout << "-----------" << endl;
}

2、当使用delete或delete[] 释放堆内存上的类对象时,会自动调用析构函数(必须使用delete释放)。

#include <iostream>
using namespace std;

struct Student
{
    int id;
    string name;
    char sex;
    short age;
    float score;
public:
    Student(void)
    {
        cout << "我是无参构造函数" << endl;
    }
    Student(int _id,const string& _name,char _sex,short _age,float _score)
    {
        id = _id;
        name = _name;
        sex = _sex;
        age = _age;
        score = _score;
        cout << "我是有参构造" << endl;
    }
    ~Student(void)
    {
        cout << "我是析构函数" << endl;
    }
};

int main(int argc,const char* argv[])
{

    // 使用new 或 new[] 在堆内存上创建类对象时会自动调用构造函数
    Student* stup = new Student;
    Student* stus = new Student[10];

    // 类对象的个数,也是执行构造、析构函数的次数
    cout << *((int*)stus-1) << endl;

    // 使用delete 或 delete[] 释放堆内存上的类对象时会自动调用析构函数
    delete stup;
    delete[] stus;

	// 注意:使用new创建的就使用delete释放,使用new[]创建的就使用delete[]释放,不能混用
    return 0;
}
4、析构函数要注意的问题

如果没有显式实现析构函数,那么编译器会自动生成一个什么都不做的析构函数。

如果构造函数中使用new、malloc分配的堆内存,就一定要显式实现析构函数,并在析构函数中释放堆内存,否则就会造成内存泄漏。

五、初始化列表与const成员

const成员

使用const修饰的类、结构、联合的成员变量,在类对象创建完成前一定要初始化。

不能在构造函数中初始化const成员,因为执行构造函数时,类对象已经创建完成,只有类对象创建完成才能调用成员函数,构造函数虽然特殊但也是成员函数。

在定义const成员时进行初始化,该语法只有在C11语法标准下才支持。

初始化列表

在构造函数小括号后面,主要用于给const成员初始化的一种特殊语法,也可以给普通成员初始化(可以解决参数名与成员变量名同名的问题)。

注意:如果有成员是类、结构、联合类型的,还可以在初始化列表中显式调用成员的构造函数,还可以调用父类的构造函数。

class 类名
{
	成员变量;
public:
    构造函数(参数列表):成员变量(初始值),成员变量(初始值),...
    {
        
    }
};
#include <iostream>
using namespace std;

class Test
{
    // 可以使用,但只有C11标准才支持
    // const int num = 1234;
    const int num;
public:
    Test(int num=0):num(num)
    {   
        cout << "我是带初始化列表的构造函数" << endl;
    }   
    void show(void)
    {   
        cout << "const num = " << num << endl;
    }   
};
int main(int argc,const char* argv[])
{
    Test t(123456789);
    t.show();
    return 0;
}

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

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

相关文章

动动手指探索世界,旅游APP如何定制开发?

旅游APP的出现为旅行带来了许多便利。随着移动互联网的发展&#xff0c;旅游行业也在不断寻求创新与变革。旅游APP为游客提供了更加便捷的旅行体验&#xff0c;通过旅游APP&#xff0c;用户可以了解旅游信息、旅游服务、在线咨询等&#xff0c;实现在线一站式解决旅行需求的目标…

Github 2024-09-23 开源项目周报 Top15

根据Github Trendings的统计,本周(2024-09-23统计)共有15个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目6C++项目3C项目3HTML项目2PowerShell项目1TypeScript项目1JavaScript项目1Blade项目1PHP项目1Bootstrap 5: Web上开发响应式、移动优…

【文心智能体】 旅游手绘手帐 开发分享 零代码 手绘风景 记录行程和心情 旅游攻略

旅游手绘手帐&#xff0c;点击文心智能体平台AgentBuilder | 想象即现实 (baidu.com) 目录 背景 创作灵感 开发历程 一、基础配置 二、高级配置 三、引导示例&#xff08;提示词&#xff09; 期待优化 背景 这个智能体是一个零代码智能体&#xff08;文心智能体平台现…

MySQL篇(管理工具)

目录 一、系统数据库 二、常用工具 1. mysql 2. mysqladmin 3. mysqlbinlog 4. mysqlshow 5. mysqldump 6. mysqlimport/source 6.1 mysqlimport 6.2 source 一、系统数据库 MySQL数据库安装完成后&#xff0c;自带了一下四个数据库&#xff0c;具体作用如下&#xf…

JDBC和一下重要的jar包,分层结构

系列文章目录 JDBC和方便使用的jar包 目录 系列文章目录 文章目录 一、JDBC 1.步骤 2.SQL注入 3.SQL注入解决&#xff08;PreparedStatement&#xff09; 4.批处理和事务控制 5.连接池 Druid连接池&#xff08;德鲁伊&#xff09; 6.封装为工具类 7.ThreadLocal 、小秘书 二、…

大语言模型(LLM)入门学习路线图

Github项目上有一个大语言模型学习路线笔记&#xff0c;它全面涵盖了大语言模型的所需的基础知识学习&#xff0c;LLM前沿算法和架构&#xff0c;以及如何将大语言模型进行工程化实践。这份资料是初学者或有一定基础的开发/算法人员入门活深入大型语言模型学习的优秀参考。这份…

【FPGA】FPGA芯片结构

目录 1 可编程输出/输出单元&#xff08;IOB&#xff09;2 可配置逻辑块&#xff08;CLB&#xff09;3 数字时钟管理模块&#xff08;DCM&#xff09;4 嵌入式块存储器&#xff08;BRAM&#xff09;5 布线资源6 内嵌功能模块&#xff08;专用IP单元&#xff09;6.1 PLL&#xf…

SpringBoot简易商品管理系统

> 这是一个基于SpringBootThymeleaf实现的简易商品管理系统。 > 包含基本的登录/注册与商品管理功能。 > 界面简洁美观&#xff0c;代码结构清晰&#xff0c;适用于JAVA初学者在此基础上进行二次开发。 一、项目演示 二、技术框架 框架描述Spring Boot容器管理 S…

CV之OCR:GOT-OCR2.0的简介、安装和使用方法、案例应用之详细攻略

CV之OCR&#xff1a;GOT-OCR2.0的简介、安装和使用方法、案例应用之详细攻略 目录 GOT-OCR2.0的简介 1、更新 GOT-OCR2.0的安装和使用方法 1、安装 安装环境cuda11.8torch2.0.1 安装包 安装Flash-Attention GOT权重&#xff1a;1.43G 2、演示 3、训练 4、评估 GOT-…

Tomcat靶场攻略

一.CVE-2017-12615 1.首页抓包&#xff0c;修改为 PUT 方式提交 ,将jsp木马写到数据包中 2.哥斯拉默认秘钥连接 二.后台弱⼝令部署war包 1.制作WAR包,上传 将JSP⽊⻢压缩为ZIP格式&#xff0c;然后修改后缀为war 2.文件上传成功后&#xff0c;默认会在网站根目录下生成和wa…

使用centos7搭建wiki论坛,使用nginx网站来搭建wiki负载均衡,反向代理。

1.安装一个wget&#xff0c;进入目录opt下 #安装wget yum -y install wget#进入目录/opt/下面 cd /opt/2.获取 mysql8.0 rpm包,安装mysql8.0,安装mysql-server&#xff0c;yum会自动下载所需安装及依赖包. #获取 mysql8.0 rpm包 wget https://dev.mysql.com/get/mysql80-comm…

2024人工智能结课作业-DFS/BFS/Astar解决数码问题

1 深度优先遍历搜索(DFS) 1.1算法介绍 深度优先搜索算法&#xff08;Depth-First-Search&#xff0c;DFS&#xff09;是一种用于遍历或搜索树或图的算法。沿着树的深度遍历树的节点&#xff0c;尽可能深的搜索树的分支。当节点v的所在边都己被探寻过&#xff0c;搜索将回溯到发…

基于SSM的“在线CRM管理系统”的设计与实现(源码+数据库+文档+开题报告)

基于SSM的“在线CRM管理系统”的设计与实现&#xff08;源码数据库文档开题报告) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SSM 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 总体功能模块图 登录页面 后台管理页面 产品信息页面 客…

【Android】BottomSheet基本用法总结(BottomSheetDialog,BottomSheetDialogFragment)

BottomSheet BottomSheet 是一种位于屏幕底部的面板&#xff0c;用于显示附加内容或选项。提供了从屏幕底部向上滑动显示内容的交互方式。这种设计模式在 Material Design 中被广泛推荐&#xff0c;因为它可以提供一种优雅且不干扰主屏幕内容的方式来展示额外信息或操作。 具体…

大型综合医院供配电系统设计

摘要&#xff1a;众所周知&#xff0c;医院供配电系统关系着整个医院的正常运行&#xff0c;一旦出现故障将会对病患的安全造成威胁。基于此&#xff0c;本文就大型综合医院供配电系统设计进行深入探讨&#xff0c;以期为其他类似医院建筑供配电系统设计提供借鉴。 关键词&…

代理模式详解:控制对象访问的利器

代理模式&#xff08;Proxy Pattern&#xff09;是一种结构型设计模式&#xff0c;它为其他对象提供一种代理以控制对这个对象的访问。代理模式通常用于延迟对象的创建、控制对对象的访问或在访问对象时添加一些额外的操作。 代理模式通过引入一个代理对象来控制对目标对象的访…

超详细超实用!!!AI编程之cursor配置中文(一)

云风网 云风笔记 云风知识库 一、配置中文扩展 打开扩展&#xff0c;搜索chinese,安装chinese(simplified) 简体中文语言包,重启即可 二、配置中文方法二 使用快捷键组合【CtrlShiftp】&#xff0c;在搜索框中输入configure display language,选择中文也可配置中文 三、配置…

九、成功版--windows上安装artifactory配置postgressql

centos上搞不定&#xff0c;windows上搞定了 现阶段是想用java写程序控制制品库&#xff0c;等以后研究多了需要写一些脚本的时候&#xff0c;在研究linux上安装artifactory&#xff08;公司就用的linux安装的配置mysql&#xff0c;有空对着配一下linux的&#xff09; 源码地…

【实证数据】国家信息消费试点城市(2000年-2023年)

数据说明&#xff1a;2013年&#xff0c;国务院发布《促进信息消费若干意见》&#xff0c;旨在激发需求、拓宽市场及丰富服务内容。随后&#xff0c;工信部启动信息消费试点城市建设&#xff0c;分两批确立104个试点区域&#xff0c;旨在通过试点引领&#xff0c;促进信息消费增…

STM32—I2C通信外设

1.I2C外设简介 STM32内部集成了硬件I2C收发电路&#xff0c;可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能&#xff0c;减轻CPU的负担支持多主机模型&#xff08;可变多主机&#xff09;支持7位/10位地址模式&#xff08;11110......)支持不同的通…