C++之基础(一)

主要内容
从C到C++
类和对象
操作符重载
继承与多态
异常和IO流




一,更好的C
1,语言风格更加简洁
2,类型检查更严格
void func(unsigned char* puc0{...}
int main(void){
   func("hello");//报错 hello是const char*。指向的是字符串常量
//而函数参数不是const类型
   return 0;
}


3,支持真正意义上的枚举类型
enum seaon{SPR,SUM,AUT,WIN};
SPR,SUM,AUT,WIN代表整数
season s = 0;
但是在C++中是错误的
C++中的枚举是真正的数据类型


4,参数匹配更精确
void func(int n){...}
void func(char c){...}
int main(void){
   func('c');//根据参数的准确性进行匹配
}


5,禁止使用隐式声明
int main(void){


   int n = func();
}
int func(void){


   return 10;
}
在C中,如果返回值类型是int的,那么可以不声明
如果在C++中,则报错
在C++中没有隐式声明的那回事儿与上面的1,4是有联系的


二,第一个C++程序
hello.cpp
#include <iostream>
int main(void){
   std::cout << "Hello C++ !" << std::endl;
   std::cout << 123 << std::endl;
   std::cout << 'A' << std::endl;
   return 0;
}


注:"<<"是插入运算符
gcc编译C程序,g++编译C++程序


三,命名空间
1,名字空间指令
using namespace 名字空间名


2,名字空间声明
using 名字空间名::标识符


3,无名名字空间(匿名名字空间成员)
namespace{


   名字空间成员;
}
引用方式:
::名字空间成员;
名字空间成员;


noname.cpp
#include <iostream>
using namespace std;
namespace{
   void foo(void){


cout << "foo()" << endl;
   }


}


void bar(void){//放在C++的无名名字空间中


  cout << "bar()" << endl;
}


namespace ns1{
  void foo(void){
cout << "ns1的foo()" << endl;
  }


}
int main(void){
  ::foo();//两种调用方式
  foo();


  bar();
  ::bar();
  return 0;
}


全部是调用了无名名字空间里面的foo()函数
注:在C++中,任何东西都是在名字空间中的,没有定义的就放在无名的里面


int main(void){
  using ns1::foo;
  ::foo();
  foo();
  return 0;
}
无名的foo()
ns1中的foo();
在此处无名名字空间的foo()必须加::


四,C++的结构,联合和枚举(自定义数据类型)
1,C++的结构里面可以定义函数
2,C++里定义结构型变量的时候可以省略struct关键字
struct.cpp
#include<iostream>
using namespace std;
struct Student{
   char name[128];
   int age;
   
   void print(void){
     cout << name <<", " << age << endl;
   }
}


int main(){
   struct Student s = {"张飞",28};
   Student ss = {"赵云",33};
   printf("%s,%d\n",s.name,s.age);
   s.print();
   return 0;
}




3,C++中的声明联合类型的变量可以不加union关键字


int main(){
  union{
    int x;
    char c[4];
  };
  x = 0x12345678;//c与x是重叠的
  printf("%02X,%02X,%02X,%02X\n",c[0],c[1],c[2],c[3]);
  return 0;
}
上面的程序还可以判断内存是小端还是大端地址


4,C++的枚举是一个独立的数据类型,而不是整数类型


五,C++的bool类型
C99中有了bool类型,但实际上是一个宏
bool类型变量只可以取true或者false 


bool b = true;
bool b2 = false;
cout << b << ","<< b2 << endl;
结果:1,0
cout << boolalpha << b << "," << b2 << endl;
结果:true,false
cout << sizeof(bool) << endl;
结果是1
b=3.14;
cout << b << endl;
结果是:true


编译器认为非0都是true。


六,C++的运算符转换
&& and
|| or
&  bitand
|  bitor


七,C++的函数
1,重载:在同一作用域中,函数名相同,参数表不同的
函数之间构成重载关系


函数原型:函数类型+函数名+函数形参表
函数签名:函数名+函数形参表
C语言中,同一作用域中,函数名必须是唯一的
C++语言中,同一作用域中,函数签名必须是唯一的


完全匹配>常量转换>升级转换>标准转换>自定义转换>省略号匹配
常量转换:形参是常量,实参是变量,这样转换安全
标准转换:损失精度




int foo(char c){...}
int (*pfunc)(char) = foo;//函数指针
pfunc('A');
当使用函数指针的时候,有多个函数,但是要调用哪个函数呢?


函数指针的类型决定其具体指向的重载版本,而不是由实参的类型决定




为什么C语言中不可以函数重名,而C++可以呢?
因为在编译的时候进行了函数名置换


通过extern "C"可以指示编译器以C语言的方式处理函数(不做函数名置换)
防止一个C文件一个C++文件编译过后二者之间的调用出现问题


2,缺省参数
testcpp.cpp
void bar(int n,double f = 1.2,char c = 'A'){
  cout <<n << "," << f << "," << c << endl;
}
当不给实参的时候取缺省值
注:1)缺省参数都必须靠右
2)如果为一个参数指定了缺省值,这个参数右边所有参数都必须指定缺省值
3)缺省参数和重载要避免歧义
4)缺省参数只能用在函数的声明中


3,哑元
1)函数中带有一个参数,但是不使用
2)借助哑元参数保证函数的向后兼容
3)借助哑元实现函数的重载。


4,内联 inline
#include<iostream>
using namespace std;
#define SQUARE(x) (x*x)
int main(void){
   cout << SQUARE(10) << endl;
   cout << SQUARE(3+7) << endl; //3+7*3+7
   //#define SQUARE(x) ((x)*(x))这样可以实现想要的结果
   return 0;
}
结果:100
31


宏扩展不是函数调用,不会算表达式。仅仅是字符集的替换


函数调用是有成本的,函数调用就有参数检查,保护现场,压栈等等


int square(int x){


  return x * x;
}


inline int square(int x){


  return x * x;
}
宏是在预编译的时候进行的,进行代码级的替换
内联是将二进制代码嵌入到指定的位置


总之:
1)内联函数保持了函数的特性,同时避免了函数调用的开销
2)inline关键字仅仅表示希望该函数被编译为内联,究竟会不会成内联,
由编译器决定。通常情况下,大函数和递归函数不会被处理为内联


内联是用牺牲空间换取时间


八,内存分配
new /delete ------ new和delete是操作符
new.cpp
#include<iostream>
using namespace std;
int main(){
  //C
  int* p1 = (int*) malloc(sizeof(int));
  *p1 = 123;
  cout << *p1 << endl;
  free(p1);


  //C++
  p1 = new int(123);
  cout << *p1 << endl;
  delete p1;


  p1 = new int[5];
  for(int i = 0; i < 5; i++){
p1[i] = i * 10;
  }
  delete[] p1;//delete p1;仅仅释放第一个元素,后面四个没释放
  
  return 0;
}


如果内存是以数组的形式分配的,那么也应该按照数组的方式释放
delete[]
new可能会失败,这时会抛出bad_alloc异常,程序应该捕获并处理该异常
,否则进程将被系统杀死。


九,引用
引用实际上是一个变量的别名。
ref.cpp
#include<iostream>
using namespace std;
int main(void){
  int n = 100;
  int& r = n;
  r = 20;//将20赋给了r所引用的变量
  cout << n << endl;
  int* p = &n;
  *p = 20;
  cout << n << endl;
  return 0;
}


指针可以不初始化(野指针),但是引用必须在声明的同时初始化
引用已被初始化,再不能引用其他变量




引用不能引用常量,只有const型引用才能引用常量
例如:int& rc = 10;//错误
const int& rc = 10;//正确
不能对常引用做赋值
rc = 20;//错误































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值