第一章 C++对C的扩展-1

本文介绍了C++相较于C语言的特性增强。包括类型增强,如类型更严格、有布尔类型、真正的枚举及表达式值可赋值;输入与输出方面,有标准输入输出流cin和cout及格式化设置;函数重载,涉及重载规则、调用匹配、底层实现及extern \C\的使用以兼容C类库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.类型增强

1.1类型更严格

    const类型的指针赋值给非const类型的指针。C可以编译通过,但是在C++编译不过去。

int main()
{
    const int a = 100;
    int b = a;

    const int *pa = &a;
    int *pb = pa;

    return 0;
}

1.2.布尔类型(bool)

    C语言的逻辑真假用0和非0来表示。而C++有了具体的类型。

int main()
{
    bool flag = true;
    if (flag != flase)
    {
        printfI("i know bool type now!\n");
    }

    printf("bool size = %d\n", sizeof(bool));
    return 0;
}

1.3.真正的枚举

    C语言中枚举本质就是整型,枚举变量可以用任意整型赋值。而C++中枚举变量,只能用被枚举出来的元素初始化。

enum season {SPR, SUM, AUT, WIN};
int main()
{
    enum season s = SPR;
    //s = 0; //error
    return 0;
}

编译error

F:\qt-test\const\main.cpp:9: 错误:invalid conversion from 'int' to 'season' [-fpermissive]

1.4.表达式的值可被赋值

    C语言中表达式通常不能作为左值, 即不可被赋值,C++中某些表达式是可以被赋值的。

int main()
{
    int a, b = 5;
    (a = b) = 100;

    cout << "a = " << a << " b = " << b << endl;

    (a<b?a:b) = 200;
    cout << "a = " << a << " b = " << b << endl;

    return 0;
}

二.输入与输出(cin/cout)

    第一一个真正意义上的C++程序, C++程序的后缀为cpp。假设程序名叫xxx,则应该写成xxx.cpp。

2.1.cin && cout

    cin和cout是C++的标准输入流和输出流。他们在头文件iostream中定义。

流名含义隐含设备流名含义隐含设备
cin标准输入键盘cerr标准错误输出屏幕
cout标准输出屏幕clogcerr的缓冲输出屏幕
int main()
{
    char name[30] = {0};
    int age;

    cout << "pls input name and age:" << endl;
    cin >> name;
    cin >> age;
    //cin >> name >> age;

    cout << "your name is :" << name << endl;
    cout << "your age is:" << age << endl;

    return 0;
}
//string name 安全性对比
//%d%c 的问题

2.2.格式化

    C语言中printf拥有强大的格式化控制。C++亦可以实现,略复杂。

2.2.1.设置域宽及位数

    对于实型,cout默认输出六位有效数据,setprecision(2)可以设置有效位数,setprecision(n) << setiosflags(ios::fixed)合用,可以设置小数点右边的位数。

#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    printf("%c\n%d\n%f\n", 'a', 100, 120.00);
    printf("%5c\n%5d\n%6.2f\n", 'a', 100, 120.00);

    cout << setw(5) << 'a' << endl << setw(5) << 100 << endl << setprecision(2) << setiosflags(ios::fixed) << 120.00 << endl;

    return 0;
}

2.2.2. 按进制输出 

       输出 十进制,十六进制,八进制。默认输出十进制的数据。

int i = 123;

cout << i << endl;
cout << dec << i << endl; //十进制
cout << hex << i << endl; //十六进制
cout << oct << i << endl; //八进制
cout << setbase(16) << i << endl; // 8为八进制 16为十六进制 其他值为十进制

2.2.3.设置填充符

    还可以设置域宽的同时,设置左右对齐及填充字符。

int main()
{
    cout<<setw(10)<<1234<<endl;
    cout<<setw(10)<<setfill('0')<<1234<<endl;
    cout<<setw(10)<<setfill('0')<<setiosflags(ios::left)<<1234<<endl;
    cout<<setw(10)<<setfill('-')<<setiosflags(ios::right)<<1234<<endl;

    return 0;
}

三.函数重载

3.1.引例

    如下函数分别求出整理数据和浮点数据的绝对值:

int iabs(int a)
{
    return a>0?a:-a;
}

double fabs*(double a)
{
    return a>0?a:-a;
}

    C++致力于简化编程,通过函数重名来达到简化编程的目的。

int abs(int a)
{
    return a>0?a:-a;
}

double abs*(double a)
{
    return a>0?a:-a;
}

3.2.重载规则与调用匹配(overload&match)

    重载规则:

  1. 函数名相同
  2. 参数个数不同,参数的类型不同,参数的顺序不同,均可构成重载
  3. 返回值类型不同则不可构成重载

如下:

void func(int a); //ok
void func(char a); //ok
void func(char a,int b); //ok
void func(int a, char b); //ok
char func(int a); //与第一个函数有冲突

    有的函数虽然有返回值类型,但不与参数表达式运算,而作一条单独的语句。

    规则匹配:

  1. 严格匹配,找到则调用
  2. 通过隐式转换寻求一个匹配,找到则调用
#include <iostream>
using namespace std;
void print(double a){
cout<<a<<endl;
}v
oid print(int a){
cout<<a<<endl;
}i
nt main(){
print(1); // print(int)
print(1.1); // print(double)
print('a'); // print(int)
print(1.11f); // print(double)
return 0;
}

注:

C++允许,int 到 long和double,double 到 int和float隐式类型转换 。遇到这种情形,则会引起二义性。

解决方法,在调用时强转。

3.3.重载底层实现(name mangling)

    C++利用name mangling*(倾轧)技术,来改名函数名,区分番薯不用的同名函数。

    实现原理:用v-c-i-f-l-d表示void char int float long double及其引用。

void func(char a); // func_c(char a)
void func(char a, int b, double c);
//func_cid(char a, int b, double c)

3.4.extern "c"

    name manling 发生在两个阶段, .cpp编译阶段,和.h的声明阶段。只有两个阶段同时进行,才能匹配调用。

mystring.h

extern "C" {
int myStrlen(char *str);
}

mystring.cpp

int myStrlen(char *str)
{
    int len = 0;
    while(*str++)
    len++;
    return len;
}

main.cpp

#include <iostream>
#include "mystring.h"

using namespace std;

int main()
{
    char *p = "china";
    int len;
    len = myStrlen(p);
    return 0;
}

    C++完全兼容C语言,那就面领着,完全兼容C的类库。由.c文件的类库文件函数名,并没有发生name mangling行为,而我们在包含.c文件所对应的.h文件时,.h文件要发生name mangling行为,因而会发生链接的时候的错误。

    C++为了避免上述错误的发生,重载了关键字extern。只需要,要避免name mangling的函数前, 加extern "C" 如多个, 则extern "C"{}

    我们看一个系统是怎么处理的:

string.h

extern "C" {
    char * __cdecl _strset(char *_Str,int _Val) __MINGW_ATTRIB_DEPRECATED_S
EC_WARN;
    char * __cdecl _strset_l(char *_Str,int _Val,_locale_t _Locale) __MINGW
_ATTRIB_DEPRECATED_SEC_WARN;
    char * __cdecl strcpy(char * __restrict__ _Dest,const char * __restrict
__ _Source);
    char * __cdecl strcat(char * __restrict__ _Dest,const char * __restrict
__ _Source);
    int __cdecl strcmp(const char *_Str1,const char *_Str2);
    size_t __cdecl strlen(const char *_Str);
    size_t __cdecl strnlen(const char *_Str,size_t _MaxCount);
    void *__cdecl memmove(void *_Dst,const void *_Src,size_t _Size) __MINGW
_ATTRIB_DEPRECATED_SEC_WARN;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值