C++对C的扩展(上)

简介: C++对C的扩展

C++对C的扩展


::作用域运算符


通常情况下,如果有两个同名变量,一个是全局变量,一个是局部变量,那么局部变量在其作用域中有较高的优先权, 它将屏蔽全局变量(就近原则)


代码示例

#include <iostream>
#include <string>
#include <iostream>
using namespace std;
int a = 10;
void test()
{
    int a = 20;
    cout << a << endl;
    cout << ::a << endl;
}
int main(int argc, char* argv[])
{
    test();
    return 0;
}


namespace 命名空间


在C++中,名称可以是符号常量、变量、函数、结构、枚举、类和对象等。工程越大,名称相互冲突的可能性越大。另外使用多个厂商的类库时,也可能导致名称冲突。为了避免在大规模程序设计中,以及在程序员使用各种各样的C++库的时候,这些表示符的命名发生冲入,标准的C++引入关键字namespace,可以更好的控制标识符的作用域。


代码示例

#include <iostream>
#include <string>
#include <iostream>
using namespace std;
namespace A
{
    int a = 10;
    namespace C
    {
        int a = 200;
    }
    void c()
    {
        cout << "A :: C" << endl;
    }
}
namespace B
{
    int a = 20;
    void c();
}
void B::c()
{
    cout << "B :: C" <<endl;
}
void test()
{
    cout << A::a << endl;
    cout << A::C::a << endl;
    cout << B::a << endl;
    A::c();
    B::c();
}
int main(int argc, char* argv[])
{
    test();
    return 0;
}


命名空间的使用注意


  • 命名空间只能在全局范围定义
  • 命名空间内可以嵌套命名空间
  • 命名空间是开放的,可以随时把新的成员加入已有的命名空间中
  • 命名空间可以存放变量、函数、类等
  • 命名空间中的函数可以在命名空间外部定义


无名命名空间和命名空间别名


意味着命名空间的标识符只能在本文件内访问,相当于给这个标识符加上了static,使得其可以作为内部连接

#include <iostream>
#include <string>
#include <iostream>
using namespace std;

namespace
{
    int a =300;
    void func()
    {
        cout << " im 啊" <<endl;
    }
}
namespace vewrylongnamespace
{
    void func()
    {
        cout << "vewrylongnamespace" <<endl;
    }
}
void test()
{
    cout << a << endl;
    func();
    namespace aa = vewrylongnamespace;
    aa::func();
}
int main(int argc, char* argv[])
{
    test();
    return 0;
}


using声明


  • 表示从using开始,下面的变量使用using声明的命名空间中优先获取,简化对命名空间成员访问的操作。
  • 简化的代价是容易造成命名空间的冲突。
  • using 指明使用具体的命名空间的成员。如果出现冲突则会报错,不会和全局变量冲突。
  • using遇到函数重载的时候,指定函数会对所有的函数起作用。
#include <iostream>
#include <string>
#include <iostream>
using namespace std;
namespace A
{
    int a = 10;
}
namespace vewrylongnamespace
{
    int a = 20;
}
void test()
{
    // int a = 100;
    using namespace A;
    // using A::a;
    cout << a << endl;
}
int main(int argc, char* argv[])
{
    test();
    return 0;
}
#include <iostream>
#include <string>
#include <iostream>
using namespace std;
namespace B
{
    int a = 20;
    void func()
    {
        cout << "B" <<endl;
    }
    void func(int a)
    {
        cout << "func with a" <<endl;
    }
}
void test()
{
    using B::func;
    func(1);
}
int main(int argc, char* argv[])
{
    test();
    return 0;
}


注意: 不同命名空间的同名成员使用的时候注意二义性。


语法的增强


  • 全局变量的增强检测
  • 类型检查增强,函数参数和返回值必须有类型,不可以缺省
  • 严格的类型转换
  • struct类型加强


struct的增强


  • C中定义结构体在使用的时候需要加上struct关键字, C++不需要
  • C中的结构体只能定义变量,不能定义成员函数, C++都可以


bool 类型


标准C++的bool类型有两种内建常量(true 和false)表示状态,占一个字节大小,只有两个值

C99之后才有和C++一样的bool值。


三目运算符


C语言三目运算符返回的为数据值,为右值,不能赋值

C++返回的为变量本身(引用), 为左值,可以赋值


const 关键字


C语言


  • const 修饰全局变量,内存空间在文字常量区(属于全局区,只读),不能通过num的地址修改空间内容。
  • const修饰局部变量时,变量名只读,内存在栈区(可读可写),可以通过变量的地址间接修改空间内容。


C++


  • 在C++中一个const不必创建内存空间,是否分配依赖于如何使用;而在C中一个const总是需要一块内存空间。
  • 在函数之外的const默认是内部连接,在其他文件无法访问。如果想在别的文件中使用则必须加extern。
  • C++中对于基础类型,系统不会给data开辟空间,系统会把数据放入符号表中,data可以看成真正的常量。
  • 对data取地址的时候,系统会给data开辟内存空间。
  • 使用一个变量给只读变量初始化的时候也会开辟空间,这种情况下不会将const变量放入符号表中,因此可以修改其值。
  • 对于自定义数据类型,也会开辟空间。
  • 尽量使用const替换宏。
#include <iostream>
#include <string>
#include <iostream>
using namespace std;
void test()
{
    const int data = 10;
    cout << data << endl;
    int *p = (int *)&data;
    *p = 2000;
    cout << *p << endl;
    cout << data << endl;
    int a = 10;
    const int b = a;
    int *pp = (int *)&b;
    *pp = 200;
    cout << *pp << endl;
    cout << b << endl;

}
int main(int argc, char* argv[])
{
    test();
    return 0;
}

const 替换define


  • const 有类型,可以进行编译器类型安全检查,#define没有类型,不会进行类型检查
  • const有作用域,而#define没有作用域,默认到文件末尾都是有效的


引用


引用是C++对C的重要扩充。在C/C++中,指针的作用基本都是一样的,但是在C++中增加了另外一种给函数传递地址的途径,这就是按引用传递,它也存在于其他语言中,不是C++发明的。


语法:

  • &和别名结合表示引用
  • 给某个变量取别名,就定义某个变量
  • 从上往下替换
int num = 10;
int &a = num; // 表明a是引用变量, a是num的别名


注意:

  • 引用必须初始化
  • 一旦初始化,不能随便修改


C++对C的扩展(下):https://developer.aliyun.com/article/1459383

目录
相关文章
|
2月前
|
设计模式 uml C++
C++中的装饰器模式:灵活地扩展功能
C++中的装饰器模式:灵活地扩展功能
45 0
|
2月前
|
安全 编译器 程序员
C++对C的扩展(下)
C++对C的扩展
36 0
|
2月前
|
算法 数据处理 C++
【C++ 20 新特性 算法和迭代器库的扩展和泛化 Ranges】深入浅出C++ Ranges库 (Exploring the C++ Ranges Library)
【C++ 20 新特性 算法和迭代器库的扩展和泛化 Ranges】深入浅出C++ Ranges库 (Exploring the C++ Ranges Library)
307 1
|
1月前
|
程序员 C语言 C++
【C++语言】继承:类特性的扩展,重要的类复用!
【C++语言】继承:类特性的扩展,重要的类复用!
|
2月前
|
算法 Java C++
【C/C++ 内存知识扩展】内存不足的可能性分析
【C/C++ 内存知识扩展】内存不足的可能性分析
24 0
|
2月前
|
存储 编译器 C++
C++新特性 扩展和聚合类型
C++新特性 扩展和聚合类型
|
11月前
|
安全 编译器 C语言
c++学习之c++对c的扩展1
c++学习之c++对c的扩展1
88 0
|
2月前
|
PyTorch 算法框架/工具 C++
windows上编译安装pytorch的c++扩展
windows上编译安装pytorch的c++扩展
|
8月前
|
存储 编译器 数据处理
c语言、c++扩展介绍 ————柔性数组、零长数组。
零长数组做为一种 GNU 的语法扩展方式,为数据处理提供优化支持。 因为编译器的编译特性,这种声明方式,只是一个指向固定位置的偏移量常量, 为什么要使用零长数组
51 0
|
9月前
|
算法 C++
剑指offer(C++)-JZ71:跳台阶扩展问题(算法-动态规划)
剑指offer(C++)-JZ71:跳台阶扩展问题(算法-动态规划)