01从c到c++

c++的发展历史 

+ 80年代贝尔实验室 本贾尼
+ 83年 正式命名c++
+ 87年 gnu制定了c++标准
+ 92年 微软和IBM分别制定了c++标准
+ 98年 ansi ISO 制定了标准 c++98 
+ 03 ISO c++03 
+ 11 ISO c++11 c++0x

编译时注意:gcc ***.c -std=c99

c与c++的关系 

  • c++包含了整个c,c是建立c++的基础
  • c++是强类型的语言,对类型检查更加的严格
  • c++扩展了c:
    • c++提供了面向对象的编程机制
    • 运算符重载
    • 异常处理机制
    • 泛型 模板(STL)

第一个c++程序 

#include <iostream>
using namespace std;


int main()
{
    cout << "hello world!" << endl;

    return 0;

}

 头文件 

标准c++头文件不带.h结尾,头文件在/usr/include/c++/4.6/,可以使用c的头文件
标准c头文件建议去尾加头的方式去使用,例如:

#include<stdio.h> --------> #include<cstdio>
#include<string.h> -------> #include<cstring>

非标准c头文件 该怎么用就怎么用,如:

#include<pthread.h>

 源文件 

源文件建议用.cpp后缀名,也可以是.cc .cxx .c++等

 编译器 

使用g++编译器,如果使用gcc需要加一个链接库 -lstdc++
g++的编译选项和gcc相同:

        -c   编译
        -o   输出名
        -On  优化
        -S   生成汇编
        -E   预处理
        -I   指定头文件的位置
        -L   指定库的位置
        -l   指定库名
        -std 指定编译标准
        -g   生成调试信息

 命名空间 

1、就是把一组逻辑上相关的数据组织到一起的逻辑名

  • 便于模块化
  • 防止命名冲突

2、语法

namespace 空间名
{
    //数据
    int age;
    void fun(){}
}

3、如何使用命名空间
+ 在数据前加 命名空间:: 即可
+ 使用using 声明
    using 空间名::数据名;
+ 使用using namespace 指令
    using namespace 空间名

例子:

#include <iostream>
using namespace std;

namespace IBM
{
    int age = 60;
    double salary = 5555;
    void show();
}
namespace IBM
{
    void show()
    {
        cout << "the age of IBM is " << age << ",the salary is "<< salary
        << endl;
    }
}

namespace NJUST
{
    int age = 50;
    double salary = 4444;
    void show()
    {
        cout << "the age of NJUST is " << age << ",the salary is " << salary << endl;
    }
}
// using namespace IBM;
using IBM::show;  // 易错
int main()
{
    show();
    NJUST::show();
    return 0;
}

4、无名命名空间
如果一个数据没有定义在任何命名空间,则这个数据属于无名命名空间

namespace {
            // 防止跨文件访问
            int age = 23;
    }
    ::数据;

例子:

#include<iostream>
using namespace std;

int a = 100;
namespace 
{
    int b = 123;
}

int main()
{
    cout << a <<endl;
    cout << b <<endl;
    
    cout << ::a <<endl;
    cout << ::b <<endl;
    return 0;
}

5、命名空间嵌套

#include<iostream>
using namespace std;

namespace ns1
{
    int a = 1;
    namespace ns2
    {
        int a = 2;
        void show()
        {
            cout << a <<endl;
        }
        namespace ns3
        {
            int a = 3;
            void show()
            {
                cout << "this is ns3!" <<endl;
            }
        }
    }
}

namespace ns4 = ns1::ns2::ns3;
int main()
{
    ns1::ns2::show();
    // ns1::ns2::ns3::show();
    ns4::show();
    return 0;
}

c++中的结构 联合 枚举

1、结构体
结构体的定义和c中的完全相同
c++ 中使用结构体做为类型时 可以省略关键字 struct
c++ 中的结构体中 是可以定义函数的

结构体例子

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

/* 定义一个结构体表达 日期 */
struct Date
{
    /* 成员变量 */
    int year;
    int month;
    int day;
    /* 成员函数 */
    void show()
    {
        printf("%04d-%02d-%02d\n",year,month,day);
    }
};

/* 设计一个函数 可以表现 一个日期变量的数据 */
void show_date(Date date)
{
    printf("%04d-%02d-%02d\n",date.year,date.month,date.day);  
}

int main()
{
    Date date = {2016,2,4};
    show_date(date);
    date.year = 2020;
    show_date(date);
    date.show();
    return 0;
}

2、联合体
联合体的定义和 c中的完全相同
c++ 表达联合这个类型时 可以省略 union
c++ 中支持匿名联合

联合体的例子

#include<iostream>
using namespace std;

int main()
{
    
    union 
    {
        char data[4];
        int x;
    };
    /* '0'----> 48 'A'--->65  'a'---->97*/
    x = 0x31323334;
    // x = 41424344;    D C B A
    //小端存储
    for(int i =0;i<4;i++)
        cout << data[i] <<" ";
    // 4 3 2 1
    return 0;
}

注:用这个程序可以查看大端字节或者小端字节序。

3、枚举类型
c++表达枚举类型时 可以省略关键字 enum
可以把枚举赋值给整数 整数不可以赋值给枚举变量 (c++不允许,这里体现了c++对类型检查的严格)

枚举的例子:

#include<iostream>
using namespace std;

enum Direction
{
    D_UP = 3,D_DOWN,D_LEFT,D_RIGHT
};


int main()
{
    Direction dire = D_LEFT;
    int x = dire;
    cout << x << endl;
    // dire = 2; // 不能把整数赋值给枚举类型的变量
    // dire = (Direction)2;

    return 0;
}

c++中的布尔类型 bool

取值 有 false true
c语言中需要导入一个头文件 #include<stdbool.h>

定义一个变量 除了下面的四个值之外 结果都是真的
0 '\0' NULL false
有时候用bool 类型 表达整数 真就是1 假就是0

c++ 中的函数

c++中的函数的参数列表严格匹配 无参代表没有任何参数 void依然可以用
int foo(void){}// c++ 可以去掉void
c++ 中不再支持函数的隐式声明 调用函数必须提前声明或者定义
函数的返回值类型 不能省略 main 函数除外

函数重载

1 在同一作用域中 函数名相同 参数列表不同的函数 构成重载(overload)关系
参数列表不同:参数的个数 类型 顺序
2 举例
使用函数指针 调用重载的函数

#include<iostream>
using namespace std;

int add (int x,int y )
{
    cout << "add(int ,int )"<<endl;
    return x + y;
}

double add(int x,double y)
{
    cout << "add(int ,double )" << endl;
    return x + y;
}

int main()
{
    int x = 3;
    double y  = 4.0;
    add(x, y);
    int (*p) (int ,int );
    p = add;
    p(2,3);
    return 0;
}

3 函数重载的原理
c编译器生成函数调用名时 只考虑函数名
c++编译器生成函数名时 不但考虑函数名 而且考虑参数列表
4 解决跨编译器调用的问题
extern "C" int getmax(int x,int y);

例子:
func.c

#include<stdio.h>

int getmax(int x,int y)
{
    printf("getmax is c function!\n");
    
    return x>y?x:y;
}

extern.cpp

#include<iostream>
using namespace std;

// 告诉g++ 编译器 按照C语言编译器生成调用函数名

extern "C" int getmax(int x,int y);
// 分别用gcc 编译func,g++编译extern.c
// gcc -c func.c
// g++ -c extern.c
// g++ func.o exten.o
// ./a.out

int main()
{
    // _Z6getmaxii
    getmax(20,30);

    return 0;
}

内联函数

1 可以把函数的二进制代码直接复制到调用位置
这样减少了开栈和清理栈的开销
2 如何实现

        #define GETMAX(X,Y) ((X)>(Y)?(X):(Y))
inline int getmax(int x,int y)
{
    return x>y ?x:y;
}

3
小函数 频率调用 适合内联
大函数 稀少调用 不适合内联
递归函数 不能内联
inline 只是一种请求 请求成功就按照内联调用 请求不成功 就按照普通函数调用

参数哑元

1 如果一个参数只有类型 没有参数名 则叫哑元
2 作用
让参数列表匹配更加严格
保持函数的向前兼容
void encode(int pkey);
void decode(int skey);
void decode(int ); // 新函数
区分函数
++ 默认前++;
operator++();
operator++(int);

参数的默认值

1 如果一个函数的参数设定了默认值,则调用这个函数时,这个参数可以不传值,如果对这个参数传入值,则传入的值会改变为这个值
2 语法

        // void foo(int a = 1,int b,int c = 0); // error

参数的默认值必须靠右
函数声明和实现分开时 默认值在声明时指定

举例:

    /*  设计一个函数 打印一个整数数组 默认打印整数数组的前5个数据 分割符号默认使用逗号 */
#include<iostream>

using namespace std;

void print_array(int* a,int n = 5,char c = ',')
{
    for(int i=0;i<n;i++)
    {
        if(i == (n-1))
            cout << a[i]<<endl;
        else
        {
            cout << a[i] << c ;
        }
    }
    
}
int main()
{
    int a[] = {34,23,55,321,54,67,34,45};
    print_array(a);
    
    return 0;
}

c++中的动态内存分配

    new delete
    类型 *指针名 = new 类型;
    int *p = new int ;
    int *p2 = new int(100);
    
    申请多个对象的空间
    new[]     delete[]
    类型 *p = new 类型[n] 申请n个
    定位内存分配
    int *p = new(data)int[23];

c++中的类型转换运算符

    static_cast<类型>(变量)
        在某一个方向上 可以做隐式类型转换
        int* pi;
        void* pv = pi;
    dynamic_cast<类型>(变量)
        适合具有多态性的父子类之间
    const_cast<类型>(变量)
        用来去掉const修饰
    reinterpret_cast<类型>(变量)
        重新解释内存 最接近C语言的强制类型转换
        整数变指针
        指针变整数

c++之父给c程序员的建议

    1、尽量少使用宏 const enum(定义常量) 
    2、用inline代替带参的宏
    3、用namespace 避免命名冲突
    4、变量随时用随时定义 以保证变量的初始化
    5、尽量避免使用强制类型转换 如果要进行强制类型转换 尽量使用
    6、多用new delete 少使用malloc free 
    7、少使用c 风格字符串 多使用string 类型;
    8、逐渐建立面向对象的编程思想

转载于:https://www.cnblogs.com/yanyun888/p/6078693.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值