从C转入C++

发布于:2024-04-20 ⋅ 阅读:(18) ⋅ 点赞:(0)

C++是C的超集(C的扩展名一般为.CPP),在大都分时候,C程序可在C++编译器下运行,但有时会有问题,主要有以下几点:

  • 在C++中可用//表示该符号后面为注释,如:
    void main() //这是主函数
  • 在C中以可用以下标识符,但在C++中它们是关键字: asm bed_cast bad_typeid catch class const_cast delete dymanic_cast except finally friend inline namespace new operator private protected public reinterpret_cast static_cast template this throw try type_info typeid using virtual xalloc
  • 在C中,可在前面无声明和定义时,调用函数(虽会警告). 但在C++中,任何函数在调用前必须声明或定义.
  • 在C中声明函数时,可不带参数,如:
    int FuncA();//实际可能有几个参数
    而在C++中这仅能中明无参数的函数。
  • 在C中可用旧式的函数定义如:
    int FuncA(x,y)
    int x;
    int y;
    {
    ...
    }
    而在C++中这是不允许的.
  • 在C中可对任何指针赋void指针,下:
    int a;
    int *pint;
    void *pvoid=&a
    pint=pvoid; //C中可以,C++错
    C++会出错,因C++无法自动将word指针变成另一指针类型,可显式转换
    pint=(int*)pvoid;
  • C中enum,srtuct,union可和同范围内的typedef名一致,而在C++由于可只用名称引用struct等结构,如:
    struct TypeA
    {
    ...
    };
    则可用 TypeA x;定义结构型变量x。
    固不能与typedef同名,否则编译器不清楚你到底想要定义什么。
  • 另sizeof()也有两个不同点:在C中sizeof('x'),在C中相当于sizeof(int),而在C++中相当于sizeof(char)。另如有枚举
    eumu E(x,y,z);
    sizeof(x)在C中相当于sizeof(int),而在C++中为sizeof(E)。

/文档/c++001.htm#页首">返回到页首


  • 局部变量的声明
    在C中我们要声明一个局部变量,必须在块的开头任何语句前声明,在C++中你可在程序任何一个位置声明一个变量.因此一般你可在要用某个变量时才声明它,这样便于阅读与维护(你甚至可在for语句中定义)如:
    for(int i=0;i<100;i++) //在C中i必须定义在开始处
    {
    int c=12;
    c*=12;
    int a; //这在C中可是不行的
    ...
    }
  • 范围分解操作符
    我们都知道:在C中,如在内部(如函数内)声明一个与外部变量(如全局)相同的变量时,内部的变量将掩盖外部变量,(此时外部变量存在但不可见).而在C++中这个外部的变量也是可存取的,只要在该变量前加上"::"即可,如:
    double a;
    ...
    {
    int a; //声明一与外部浮点变量a相同的整型变量a
    a=3; //这个a为内部变量,整型的
    ::a=3.5; //a为外部,浮点型
    }
  • 内嵌函数(线上函数)
    如在C++中用inline定义一个函数,如:
    inline int FuncA(int a) { ...}
    则统编译器把对这个函数的调用换成实际的函数码,和宏很类似,但有两个重要的优势:1.调用函数时,编译器检查参数类型,而宏不会.2.如果表达式传递给函数,它只会求一次值.而在宏中它求两次,这有可能带来问题,如:
    ABS(--i); 若ABS是内嵌函数它和我们想的一样工作,而如ABS是宏,则i将被减两次,这可能并不是我们希望的.
    这类函数主要用在进行大的循环中,以加快速度,或在类中使用.它与一般函数的不同的是,如改变了它,则所有调用它的源文件都要重新编译.
  • 重载函数(我不知为什么有的书把重载称为过载,怪别扭的)
    在C中如你要写一个求浮点型和整型变量绝对值的函数据,那你必须写两个不同的函数(虽然它们内部非常的象)就象下面这样:
    int AbsI(int i) {...} //整型版的
    double Absd(double i) {...} //浮点版
    而在调用时,不能搞错,而在C++中你可在同一程序中多次定义同一个函数(但它们不能有完全一样的形式),则上例可定义成:
    int Abs(int i) {...} //整型版的
    double Abs(double i) {...} //浮点版
    这样在凋用时可用同一个函数名调用,程序会自动调用正确的版本,如:
    Abs(3); //整型版
    Abs(-3.5) //调浮点版
    你也可能有时调用某函数,而每次用的参数个数不一样,也可利用该功能完成.
  • 缺省函数参数
    C++可在声明函数时定义缺省参数值来减少一些编程工作,如:
    void ShowText(char *text,int length=-1,int color=0);
    这样你可用如下的方法调用:
    char *t="hello";
    ShowText(t,6,3); //这和平时用法一样
    ShowText(t,6); //省去一个参数,此时 color=0
    ShowText(t);//省了两个参数, length=-1;color=0
    调用时不能只省去中间的,如
    ShowText(t,,4); //这是错的
    它在定义时,还要注意:不能在参数表中部定义一个缺省变量,而它后面又是正常的变量,(要么它后面全是缺省变量,要么把它放在最后)如:
    void ShowText(chat *text,int length=-1;int color);//错
    缺省变量一经定义不可在同一范围内再定义(即使是一样的)如
    void ShowText(char *text,int length=-1,int color=0);//声明
    ...
    void ShowText(char *text,int length=-1,int color=0) //定义,这就是错的
    {...}
    另:在用缺省变量和重载函数时要注意它们可能造成运行时出错(编译时可能没问题,如有以下定义:
    void Display(char *buf);
    void Display(char *buf,int length=30);
    这看上去没有任何问题,但如有以下的调用,则出错;
    Display("hello"); //多义调用,程序不知到底应调哪一个
  • 引用类型
    声明为引用的变量其实是另一变量的别名,可用&定义一引用,如
    int c;
    int &b;
    b=c;
    此时b为c的别名,即c与b有同样的地址,对b的操作和对c操作是一个效果.它与指针不同,它们是同样的类型.不能将常量赋值给它:如 b=5;//错
    也可将函数参数或返回类型声明为引用,如将参数设为引用,如下
    int FuncA(int &a);
    而有以下调用:
    FuncA(b); //则如在函数内改变了a的值,则b的值也发生同样的改变
    当然此时不能有如下的调用(把常量赋给了变量)
    Func(4);
    这除了用于能改变参数的值之外,也常用于参数为结构时(此时不用将整个结构再复制一遍,有利于提高效率,此时最好也将之定义为常量(见后常量介绍)
    函数的返回值也可定义为引用,此时函数必须返回一个适当的变量,如:
    int a=0;
    int &GetA() {return a}
    void main()
    {
    int N;
    N=GetA(); //N=0,注N并不是a的引用
    GetA()=5; //a=5;相当与a=5
    ++GetA(); //a=6;相当于++a
    }
    由于函数的引用是在函数返回后用的,它不能返回已不存在的变量,特别是返回去自动变量,或是参数的引用,如下例是危险的;
    int &aa()
    {int a;
    return a;}
    int &bb(int b)
    {return b}
    这个程序并不产生编译错误,但它们的结果是无法预料的.这类函数可安全的返回全局变量,static,或动态变量(在下面的new/deldet中介绍)
  • new和delete
    C++中一般用new和delete分配和回收内存块,使用new时指定数据类型,由系统分配足以存放指定类型对象(可为各种类型)的内存块,返回该块地址作为该指定类型的指针,如:
    int *cc;
    char *ch;
    cc=new int;
    ch=new char[23]; //分配了一个 char型数组(有23个项)
    它们可由delete回收,如:
    delete cc;
    delete[] ch; //[]表示回收整个数组,而不是单个元素.
  • 常量
    可用const定义存放常量的变量,如
    const a=100;
    则a是一个常量,它不能在程序中改变,但常量并不象你想象的那么简单,它并不象#defind:
    一.常量和指针:
    这也有几种:
    1.将指针定义为常量,可随时改变指针的值,但不能改变指针指向变量的值,(相当于只读指针),如:
    const int *PCI;
    const int a=1;
    int b=2;
    PCI=&a; //OK!
    *PCI=5; //错,不可改动
    PCI=&b; //OK!
    2.将常量指针定义到非常量变量,此时指针为常量,必须在定义时初始化,此后不能再赋其它地址,但指针指向的变量可变,如:
    int a=1;
    int b=2;
    int *const CPI=&a; //注意这行!
    *CPI=5; //OK
    CPI=&b; //ERROR,不能改变指针!
    3.定义常量指针到常量对象.这时必须在定义指针时初始化,既不能改指针,也不能改指针指向的值.
    4.不能将常量的地址赋于非常量的指针
    二.常量与引用
    可以定义常量对象的引用.它可用常量初始化:
    const int a=1;
    const int &RCA=a;
    也可用变量初始化
    int b;
    const int &RCB=b;
    无论如何都不能用引用改变所指变量的值.
    三.常量和函数
    定义函数的参数或返回类型为常量.
    如将参数中的一般变量定义为常量,没有什么意义,如:
    FuncA(const int a); //a本来就不能改变
    我们知道若参数为指针或是引用,则这可改变这此变量的值,但有时,我们可能只对参数的值感兴趣(而不想改变它们的值)这时,可用常量定义参数,保证变量的改变不会有什么副作用,如:
    funcA(const int *P);
    funcB(const int &C); //无论函数如何对P,C操作,原来的值都不会改变.
    另前面讲过如函数的参数是引用,则不能用常数为参数调用该函数,但如定义为常量引用,则可以, 如:
    void FuncA(const int &r);
    void main()
    {...
    FuncA(5); //还记得前面说的么,如它只是引用,这是错的,而现在它没问题
    ...}
    如函数的返回值是一般变量,则定义返回为常量没有什么意义,但如是指针,或是引用,则使函数不能用返回值来改变指向或引用的变量.例:
    const int *funcA()
    { static int p=1; //注意这的static,若为普通变量很危险,见前引用处
    ++p;
    return &p}

    const int &funcB()
    {static int s=100;//同想请注意这个static
    --s;
    return s;}

    void main()
    {int N;
    N=*funcA(); //OK,N为一拷贝
    N=funcB(); //OK,N也为一拷贝
    *funcA()=5; //错,不可改变.
    ++funcB(); //错,这可参考一下前面"引用"的例子