前言:此为本人的一些笔记总结,只针对一部分内容,并非完整的C++对于C的扩展。
语法检查增强
C++是强语法语言,C语言中的一些不会报错的写法,在C++中会编译报错。
声明与定义
如果先后声明了两次变量,一个赋值,一个未赋值,在C语言的编译中会认为赋值的是定义,未赋值的是声明变量,编译时不会出错。但是C++不区分这是声明还是定义,所以编译时认为你重复定义了变量。
C语言
#include <stdio.h>
int a = 10 ; //赋值,当做定义。
int a ; //未赋值,当做声明。
//若无第2行,只有第3行,就是定义变量a ,只是未被初始化
C++如此做,编译会出错。C++不区分这是声明还是定义,所以编译时认为你重复定义了变量。
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int a = 10 ;
int a ;
cout<<"a = "<< a <<endl;
return 0;
}
编译结果
C++赋值,可以在声明时定义,也可以之后再赋值。赋值时直接写变量名,不要加变量类型。
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int a = 10 ;
a = 20;
cout<<"a = "<< a <<endl;
return 0;
}
函数的参数类型
C语言中函数不指定形参的类型,那么该函数可以接收任何类型的参数。
虽然C语言语法弱,但是我们可以认为避免。
#include <stdio.h>
void func(i)
{
printf("i=%d\n",i);
}
void funcs(i)
{
printf("i=%s\n",i);
}
int main(int argc, char *argv[])
{
func(100);
funcs("string");
return 0;
}
运行结果
在C++中须指定参数的类型,同名的函数若参数类型,程序在调用函数时,会跟据参数类型的不同而调用不同的函数(重构)。
#include <iostream>
using namespace std;
void func(int i)
{
cout<<"i 是 int :"<< i << endl;
}
void func(string i)
{
cout<<"i 是 string :"<< i << endl;
}
int main(int argc, char *argv[])
{
func(101);
func("love");
return 0;
}
运行结果
类型转换更严格
C++中,不同类型的变量一般是不能直接赋值的,需要相应的强制转换。
#include <iostream>
using namespace std;
typedef enum colour{ red , green , blue } color;
int main(int argc, char *argv[])
{
color mycolor = green ;
mycolor = 10 ;
return 0;
}
编译结果
以上代码,在C语言中可以通过编译。
结构体增强
C语言中定义结构体实例必须加struct,C++中可加可不加。
C++的结构体中可以定义方法函数,C语言中不可以。
C++调用结构体的函数,需要用实例调用。
#include <iostream>
using namespace std;
struct student{
int num ;
char name[32];
//结构体方法
void func(){
cout<<" 大家好,我是 "<<num<<" 号的"<<name<<",很高兴认识大家"<<endl;
}
};
int main(void)
{
struct student lucy = {100 , "lucy"} ;//C语言定义结构体实例时必须加struct
student Jack = {101 ,"Jack"}; //C++可加可不加struct
cout<<"调用成员变量 Jack.num = "<< Jack.num <<endl ;
cout<<"调用成员方法 "<<endl;
Jack.func();
return 0;
}
运行结果
增加bool类型
C++的bool类型有两种常量true(转换为整数1)和false(转换为整数0)标志状态。
bool、true、false都是关键字。
bool类型1个字节大小,赋值bool时,非零值会自动转化为true(1),0值会自动转化为false(0)。
#include <iostream>
using namespace std;
int main(void)
{
cout<<"bool值大小 :"<< sizeof(false)<<endl;
bool flag = true ;
cout<<"true = "<< flag <<endl;
flag = false ;
cout<<"false ="<< flag <<endl;
flag = 1001 ;
cout<<"flag = "<< flag <<endl;
return 0;
}
运行结果
三目运算符
C++的三目运算符返回的值为变量本身(引用),可以为左值,可以被赋值。
C语言的三目表达式返回值为数据值,为右值,不能被赋值。
int main(void)
{
int a = 101 ;
int b = 20 ;
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"======= "<<endl;
a>b?a:b = 1001 ;
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
return 0;
}
运行结果
左值(Lvalue),L代表location,表示内存可以寻址,可以赋值。
右值(Rvalue),R代表read,表示可以读取的值。
例如:int temp = 1001;temp在内存中有地址,而1001没有,但是可以读到它的值。
const 常量
C语言中const修饰全局变量,变量名只读。默认是外部链接(其他源文件也能访问)。既然是变量,就会分配内存空间。全局定义const,不能通过&地址修改空间内容。局部定义const不能通过变量名修改值,但是可以通过取地址来修改(内容存储在栈区,栈区可读写)。
#include <stdio.h>
const int num = 100 ;
//外部文件定义,使用时要先声明num
extern const int num;
int main(void)
{
printf("num = %d \n",num);
const int d = 10 ;
printf("d = %d \n",d);
int *p=(int *)&d ;
*p=200;
printf("修改d = %d \n",d);
return 0;
}
运行结果
C++中,const 定义一个不能改变的普通变量,即常量。常量不会被分配内存。
定义基础类型 const int num=10时,编译器会将标识符放到符号表中,不分配内存,当对其取地址时,才会分配内存。
在编译时,程序会从符号表中取值,而不是内存。
在函数外定义的const作用域为当前文件,其他文件不可见。
pi.cpp
const float pi=3.14 ;//main.cpp不可见此变量
main.cpp
#include <iostream>
#include <string>
using namespace std;
const int pi = 100 ;//赋值,当前文件可见
int main(void)
{
cout<<"pi ="<<pi<<endl;
}
运行结果
如果要在其他源文件使用const定义的变量,那么就需要在定义时加extern。
fun.cpp
extern const int num = 314 ;
main.cpp
#include <iostream>
#include <string>
using namespace std;
extern const int num;
int main(void)
{
cout<<"num = "<< num <<endl;
const int data = 10 ;
cout<<"data = "<< data <<endl;
int *p = (int *) &data ;
*p=200;
cout<<"*p = " << *p << endl;
cout<<"data = "<<data<<endl;
}
运行结果
以上程序中,只是修改了内存地址中的内容,由于访问变量名时,是从符号表中取值,符号表中的值并没有改变,所以值没有变化。
当const 用一个变量初始化时,系统会分配内存。修改地址空间的值,变量值也被修改。
const 自定义数据类型(结构体、对象),也会分配内存空间。
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
int b = 200 ;
const int a = b ;
cout<<"a = "<< a <<endl;
int *p = (int *) &a ;
*p=2002;
cout<<"*p = " << *p << endl;
cout<<"a = "<< a <<endl;
}
运行结果
自定义类型(结构体)
#include <iostream>
#include <string>
using namespace std;
struct student{
int num ;
string name;
};
int main(void)
{
const student Jack={100,"Jack"};
cout<<"我是"<<Jack.num<<"号的"<<Jack.name<<endl;
student *s = (student *)&Jack;
s->num = 200 ;
cout<<Jack.name<<"的号码改为:"<<Jack.num<<endl;
}
运行结果
const与#define的区别
1.编译器检查
const有类型,可以进行编辑器检查。#define无类型,不可进行类型检查。
在C++中用const 替换宏定义#define,因为宏定义在预处理阶段就将说有的标识符替换成对应的值。编译器编译时将不会出现宏定义的标识符。编译器如果报错会提示标识符出错,而不是值出错。
#include <iostream>
#include <string>
using namespace std;
#define MAX 3.14
const short mymax =1024 ;
void func(short i)
{
cout<<"short i = "<< i <<endl;
}
void func(double i)
{
cout<<"double i = "<< i <<endl;
}
int main(void)
{
func(MAX);
func(mymax);
}
运行结果
2.作用域
宏的作用域是整个文件,const的作用域看定义位置/方式。
const有作用域,而#define不重视作用域,默认是定义出到文件结尾。如果定义在指定作用域下有效的常量,那么#define就不能用。
#include <iostream>
#include <string>
using namespace std;
void func(void)
{
#define MAX 3.14
const short mymax = 1024 ;
}
extern const int myint;
int main(void)
{
cout<<"MAX = " << MAX << endl ;
// cout<<"mymax = " <<mymax << endl ;//未声明的变量
}
运行结果
调用myint变量的编译结果
3.命名空间的成员
#define 不可以作为命名空间成员,const可以。
#include <iostream>
#include <string>
using namespace std;
namespace A {
const int name_a = 100 ;
#define MY_A 200
}
int main(void)
{
cout<<"name_a = " << A ::name_a << endl ;
// cout<<"MY_A = " << A ::MY_A << endl ;//不属于命名空间
cout<<"MY_A = " << MY_A << endl ; //宏属于整个文件
}
运行结果
以命名空间调用MY_A时的编译结果