0
点赞
收藏
分享

微信扫一扫

【Python统计与数据分析实战_01】位置与分散程度的度量

Hyggelook 2023-07-19 阅读 79

目录

经典开头 — C++的历史

作用域运算符

using的用法

命名空间 - namespace

命名空间的基本使用

特殊的命名空间 - 无名命名空间

全部展开和部分展开

std — C++所有的标准库都在std命名空间内

省缺值 - 默认参数

占位参数

内联函数 - inline

函数重载

函数重载的用法

函数重载的原理剖析

引用

基础用法

常量引用与非常量引用


经典开头 — C++的历史

        C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的
程序,需要高度的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机
界提出了OOP(object oriented programming:面向对象)思想,支持面向对象的程序设计语言
应运而生。
        1982年,Bjarne Stroustrup博士在C语言的基础上引入并扩充了面向对象的概念,发明了一
种新的程序语言。为了表达该语言与C语言的渊源关系,命名为C++。因此:C++是基于C语言而
产生的,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的
程序设计,还可以进行面向对象的程序设计。

        1979年,贝尔实验室的 Bjarne 等人试图分析unix内核的时候,试图将内核模块化,于是在C语言的基础上进行扩展,增加了类的机制,完成了一个可以运行的预处理程序,称之为C with classes。语言的发展就像是练功打怪升级一样,也是逐步递进,由浅入深的过程。一下是C++的一些历史版本。

cb0dcfd278c7a8629773e4d3c2a33d06.jpeg

作用域运算符

双冒号(::)表示作用域解析运算符(Scope Resolution Operator)。它用于指定命名空间(namespace),类(class)或结构体(struct)的作用域,或者在类的成员函数外部引用类的成员。一般来说如果作用域运算符前没有任何类或者命名空间,则表示这是指定的全局作用域。用法示例如下:

/*用于在类外部定义和实现成员函数。*/
class MyClass {
public:
    static int x;
    void func();
};

int MyClass::x = 5;  // 类外定义静态成员变量

void MyClass::func() {  // 类外定义成员函数
    // 函数实现代码
}
/*用于访问命名空间中的成员。*/
namespace MyNamespace {
    int x;
    void func();
}

void MyNamespace::func() {
    // 函数实现代码
}

int main() {
    MyNamespace::x = 10;  // 访问命名空间中的变量
    MyNamespace::func();  // 调用命名空间中的函数
    return 0;
}

/*用于访问枚举类型中的值。*/
enum MyEnum {
    VALUE1,
    VALUE2
};

int main() {
    MyEnum value = MyEnum::VALUE1;  // 访问枚举类型中的值
    return 0;
}

using的用法

在C++中,using关键字常用于引入命名空间、别名和模板的成员等。下面是using关键字的几种常见用法:

1. 引入命名空间:

using namespace namespace_name;

   示例:

using namespace std;
// 可以直接使用std命名空间中的成员,无需前缀
cout << "Hello, world!" << endl;

2. 引入单个成员:

using namespace_name::member_name;

   示例:

using std::cout;
// 引入std命名空间中的cout成员
cout << "Hello, world!" << endl;

3. 定义类型别名:

using alias_name = type_name;

   示例:

using MyInt = int;
// 定义MyInt作为int的别名
MyInt num = 42;

5. 引入模板类成员:

template<typename T>
using alias_name = template_name<T>;

   示例:

template<typename T>
class MyTemplate {
public:
  void doSomething();
};

template<typename T>
void MyTemplate<T>::doSomething() {
  // 实现...
}

// 使用using引入模板类的成员
using MyAlias = MyTemplate<int>;
MyAlias obj;
obj.doSomething(); // 调用模板类的成员函数

以上是`using`关键字的一些常见用法和相应的示例。根据需要选择适合的用法,并确保理解命名空间和类型别名的概念以及它们的用法和限制。

命名空间 - namespace

命名空间的基本使用

创建名字是程序设计过程中一项最基本的活动,当一个项目很大时,它会不可避免地包含大量名字。在C++中,名称(name)可以是符号常量、变量、函数、结构、枚举、类、对象等等。工程越大,名称互相冲突性的可能性越大。而且使用多个厂商的类库时,也可能导致名称冲突。为了避免这些标识符的命名发生冲突,C++引入了namespace(命名空间)关键字,可以更好地控制标识符的作用域。用法示例:

要点概括如下:

特殊的命名空间 - 无名命名空间

其实,命名空间也可以没有名字,而这种没有名字的命名空间就叫无名命名空间。

无名命名空间的注意事项:

全部展开和部分展开

全部展开也叫全部授权,命名空间的全部展开相当于把原来私有的东西给公开了。像我们平常写的

using namespace std;

其中的std就是全部展开的,这种全部展开​​​​​意思是当前文件可以不用限制符说明,直接访问std命名空间里的内容,例如std全展开之后,我们平常写的cout就可以选择加限定符的写法 std::cout ,也可以选择不加限定符的写法直接 cout。

但这种全部展开还有一种潜在的危险,如果全部展开了多个命名空间,而这些命名空间内有同名元素,而且我们在使用时没有加域限定符来限定,那么就会造成命名冲突。或者如果全部展开的命名空间内有与当前文件元素重名的情况,且在使用时没加限定符也会引发命名冲突。

所以一个稳妥的做法就是我们在使用全部展开的命名空间下的成员时,加上域限定符来显示的指定要使用的成员是哪一个命名空间的,这样就不会有上述的危险出现了。如果想要使用全局下的元素,域限定符前面不加东西就可以了。


与全部展开相对应的时部分展开(部分授权),顾名思义,全部展开是展开命名空间下的所有元素,那么部分展开就是只展开命名空间下的一小部分元素,例如:

using std::cout;
using std::endl;

这就是只展开了std命名空间下的cout和endl,std下的元素就只有cout和endl可以使用,而且使用时不用加限定符也不用担心会出现全部展开命名冲突的危险。但局限性也是显而易见的。

std — C++所有的标准库都在std命名空间内

在C++中,标准库的所有内容都位于std命名空间中。std是C++标准库的命名空间,包含了各种类、函数和对象,用于常见的操作和功能,例如输入输出、容器、算法、字符串处理等。

当使用C++标准库的功能时,通常需要在代码中使用using语句或者使用完整的限定符来指定所需的标识符。

以下是一些常见的C++标准库的成员,它们位于std命名空间中:

省缺值 - 默认参数

C++在声明函数时可为一个或者多个参数指定默认(缺省)的参数值,当函数调用的时候如果没有指定这个值,编译器会自动用默认值代替。也就是说,设置了默认值后,有实参传入就使用实参,没有实参传入则使用默认参数。

在C++中使用默认参数时,有如下这样几个注意事项:

占位参数

在C++中,占位参数是指在函数声明或定义中使用没有具体名称的参数,占位参数通常用于表示某个参数的存在,但在函数实现中并不使用该参数。

例如:

 void(int a,int b,int,int)

后两个参数就是占位参数。

注意事项:

占位参数在日常使用中一般很少用,但并不是说没有应用场景,比如在重载++/--运算符时为了区分前置++和后置++就会使用占位参数来区分。

内联函数 - inline

在C语言中我们有时会把一些简短且频繁使用的计算写成宏,而不是函数,这样做的理由是为了执行效率,宏可以有效的避免函数调用的开销。但是在C++中,使用预处理宏会出现两个问题:

为了保持预处理宏的效率,并且像一般成员函数那样可以在类里访问自如,还能加安全性。C++引入了内联函数(inline function):在普通函数前面加上inline关键字就变成了内联函数。

内联函数具有普通函数的所有行为,但内联函数是在适当的地方像宏一样展开,省去了函数调用时候的压栈,跳转,返回等开销。内联函数虽然占用空间,但是内联函数相对于普通函数的优势是省去了函数调用时候的压栈,跳转,返回的开销。我们可以理解为内联函数是以空间换时间。

注意事项:

内联函数和宏的异同

内联函数普通函数的区别

函数重载

函数重载的用法

函数重载是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这
同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,所以常用来处理实现功能类似数据类型不同的问题。

要点概括:

函数重载的原理剖析

理解函数重载的原理之前,我们需要先认识三个东西:符号表、函数签名、函数名修饰。

  • 函数重载的底层原理就与符号表、函数签名以及函数名修饰等息息相关。

函数签名是区分不同函数的关键因素之一。函数签名包括函数的名称、参数的类型和顺序,但不包括返回值类型(这就是为什么返回值不同不能发生重载)。在支持函数重载的编程语言中,可以定义具有相同名称但参数列表不同的多个函数。编译器根据函数签名来识别和区分这些函数,以确保在函数调用时能够选择正确的函数。
函数名修饰规则在编译器中用于生成唯一的函数标识符,以便区分具有相同名称但不同参数列表的函数。函数名修饰规则根据参数的类型、顺序和个数来创建唯一的函数名。这样可以确保具有不同参数的函数在编译后具有不同的名称,以避免函数名冲突。函数名修饰规则在函数重载的实现中起到关键作用,它确保了函数重载的正确性和可用性。
而符号表中会记录具有相同名称但不同参数列表的多个函数的信息符号表中的条目包含函数的名称、修饰后的函数名、参数类型信息等。在编译或运行时,符号表用于匹配函数调用的函数签名和函数定义,以选择正确的函数进行调用。

引用

基础用法

引用,又叫取别名,是C++中一种用于别名分配的特殊语法。它允许将一个已存在的变量作为一个别名来使用,而不是创建一个新的变量。引用可以看作是一个变量的别名,它和原变量共享同一块内存。引用在C++中的使用可以提高代码的可读性和效率。

要点概括:

常量引用与非常量引用

在此之前我们需要了解一下引用绑定的概念。

常量引用:

非常量引用:

举报

相关推荐

0 条评论