输出
语法
cout << 输出的内容
1 <<
输出的内容
2 << ...
注意
:
输出的内容中endl
表示为换行
示例
#include
using namespace std;
int main(int argc, char *argv[])
{
cout << "test!" << endl;
return 0;
}
输入
语法
cin >> 变量名
1 >>
变量名
2 >> ...
示例
#include
using namespace std;
int main(int argc, char *argv[])
{
cout << "请输入
:";
#if 0
int x = 0,y = 0;
cin >> x >> y;
cout << "输入的内容是
:x=" << x << " y="<< y << endl;
#else
char str[32];
//cin >> str;
//cout << "str =" << str << endl;
cin.getline(str,sizeof(str));
cout << "str =" << str << endl;
#endif
return 0;
}
注意
qt
中有
bug
示例:
#include
using namespace std;
int x = 100;
int main(int argc, char *argv[])
{
int x = 1;
cout << "x =" << x << endl;
cout << "::x =" << ::x <
return 0;
}
2,命名空间
定义
关键字:namespace
语法
namespace [
名称
] {
成员的声明,可以具有初始化的值
;
{
内部嵌套
namespace {};
}
{声明成员函数}
{定义成员函数}
}
//
实现
namespace
中声明的函数
函数返回值类型 命名空间的名称
::
声明的函数名
(
形参列表
){
}
示例
#include
using namespace std;
namespace my
{
int x = 10;
void test01();
void test02()
{
cout << "test02" << endl;
}
}
void my::test01()
{
cout << "test01" << endl;
}
int main(int argc, char *argv[])
{
cout << "my::x =" << my::x << endl;
my::test01();
my::test02();
return 0;
}
注意
1,
命名空间只能在全局范围类定义
(
命名空间不能定义在函数中
)
#include
using namespace std;
int main(int argc, char *argv[])
{
namespace A
{
int a = 10;
}
cout << A::a << endl;
return 0;
}
//
此时报错
2,
命名空间嵌套命名空间
(
命名空间中可以嵌套命名空间
)
#include
using namespace std;
namespace A {
int a = 10;
namespace B
{
int b = 20;
}
}
int main(int argc, char *argv[])
{
cout << "A::B::b" << A::B::b << endl;
return 0;
}
3,
命名空间的开放性(随时添加新的成员
#include
using namespace std;
namespace A
{
int a = 10;
}
namespace A {
int a2 = 100;
}
int main(int argc, char *argv[])
{
return 0;
}
4,
无名命名空间
//
无名命名空间,意味着命名空间中的标识符只能在本文件内访问
#include
using namespace std;
namespace {
int a = 10;
}
int main(int argc, char *argv[])
{
cout << "::a" <<::a << endl;
return 0;
}
5,
取别名
#include
using namespace std;
namespace XXX{
int a = 10;
}
int main(int argc, char *argv[])
{
namespace A = XXX;
return 0;
}
using
关键字
作用
1:using
声明命名空间中的具体成员
#include
using namespace std;
namespace A{
int a = 10;
int b = 1;
}
int main(int argc, char *argv[])
{
//声明命名空间
A
中的
a
变量
using A::a;
//使用时可以省略空间名
::
cout << "A::b=" << A::b << endl;
return 0;
}
注意
:
容易造成同范围内的命名冲突
#include
using namespace std;
namespace A{
int a = 10;
int b = 1;
}
int main(int argc, char *argv[])
{
//声明命名空间
A
中的
a
变量
using A::a;
//使用时可以省略空间名
::
int a = 1;//此时冲突
,
报错
cout << "A::b=" << A::b << endl;
return 0;
}
作用
2:using
声明成员函数
遇到函数重载
#include
using namespace std;
namespace A{
int a = 10;
int b = 1;
void test()
{
cout << "test01" << endl;
}
void test(int x)
{
cout << "test02" << endl;
}
void test(int x,int y)
{
cout << "test03" << endl;
}
}
int main(int argc, char *argv[])
{
//
声明命名空间
A
中的所有
test
函数
using A::test;
test();
test(10);
test(1,2);
return 0;
}
作用
3:
声明整个命名空间
注意:
当声明的作用域中的变量与成员变量重名,
有冲突
当声明的作用域中的变量与局部变量重名,
优先使用局部变量
#include
using namespace std;
namespace A{
int a = 10;
int b = 1;
void test()
{
cout << "test01" << endl;
}
void test(int x)
{
cout << "test02" << endl;
}
void test(int x,int y)
{
cout << "test03" << endl;
}
}
int main(int argc, char *argv[])
{
//
声明整个命名空间
A
using namespace A;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
test();
test(10);
test(1,2);
return 0;
}
3,全局变量类型检测增强
#include
using namespace std;
int a = 10;//
赋值并定义
int a; //c
语言认知为声明
,
通过
,c++
认为是定义
,
报错
int main(int argc, char *argv[])
{
return 0;
}
4,C++中所有的变量和函数都必须有类型
C
的自定义函数时,形参变量可以没有数据类型,即为任意类型
,
警告但是可以编译通
过
,
并可以运行
c++
中,函数的形参变量必须指定类型。没有形参建议写
void
c语言代码
#include
//c
语言中形参可以没有数据类型
,
此时形参可以为任意类型
//c++
中形参必须有类型
,
没有形参建议写
void
void fun(i)
{
printf("%d\n",i);
}
int main(int argc, char const *argv[])
{
fun(10);
return 0;
}
5,更严格的类型转换
在
C++
中
,
不同类型的变量之间赋值时,需要明确的类型转换。基本类型小转大除外
C语言代码
#include
#include
#include
int main(int argc, char const *argv[])
{
//
按
c
的方式自动转换
int a = 65;
char b = a;
printf("%c\n",b);
//
在
C
中没有问题
char *p = malloc(32);
strcpy(p, "gl");
return 0;
}
c++代码
#include
#include
#include
using namespace std;
int main(int argc, char const *argv[])
{
//
按
c
的方式自动转换
int a = 65;
char b = a;
cout << "b=" << b << endl;
// c++
必须强转(明确数据类型)
,c
语言可以不用
char *p = (char *)malloc(32);
strcpy(p, "gl");
cout << "p=" << p << endl;
return 0;
}
6,struct类型加强
1,
在
C++
中,定义结构体变量时,不用加
struct
示例
#include
using namespace std;
struct Stu
{
int id;
char name[30];
};
int main(int argc, char const *argv[])
{
Stu s = {1, "gl"};
cout << "id=" << s.id << ", name=" << s.name << endl;
return 0;
}
2,struct
类型中可以有成员函数
示例
#include
using namespace std;
struct Stu
{
int id;
char name[30];
void eat()
{
cout << name << "吃饭" << endl;
}
};
int main(int argc, char const *argv[])
{
Stu s = {1, "gl"};
s.eat();
return 0;
}
7、新增bool 类型关键字
标准
c++
的
bool
类型有两种内建的常量
true(
转换为整数
1)
和
false(
转换为整数
0
)
非标准
c++
的
bool
类型有两种内建的常量
true(
转换为非
0)
和
false(
转换为整数
0
)
占
1
字节
示例
#include
using namespace std;
int main(int argc, char const *argv[])
{
bool b1 = true;
bool b2 = false;
cout << "b1 = " << b1 << endl;
cout << "b2 = " << b2 << endl;
cout << "sizeof(bool) = " << sizeof(bool) << endl;
return 0;
}
8,三目运算符功能增强
C
中三目运算表达返回是变量的值, 而
c++
中,三目运算表达式返回是变量
示例
int a=10,b=20;
//c
编译失败
//c++
成功
(a>b?a:b) = 100;
cout << "a=" << a << " b=" << b << endl;
9,const (重要)
1,c
语言中
const
修饰的变量为只读变量
#include
int main(int argc, char *argv[])
{
const int num = 10;
//c语言中使用
const
修饰变量为只读变量
//此时无法通过变量名修改其值
//num = 11;
//但是可以通过指针变量修改值
int *p = #
*p = 11;
printf("%d\n",num);
return 0;
}
2,c++
中
const
修饰变量 如果以常量初始化该变量 不会立即开辟空间而是产生符号常量表
,
当
对其取地址会开辟新的内存地址
#include
using namespace std;
int main(int argc, char *argv[])
{
const int num = 10;
//此时
num
在符号常量表中
,
所以也无法通过变量名修改其值
//num = 11;
//当对该变量获取地址值
,
会为其开辟新的内存地址
int *p = (int *)&num:
*p = 11;
cout << "num =" << num << endl;
cout << "*p =" << *p << endl;
return 0;
}
3,
如果以变量的形式初始化
const
变量
不会产生符号常量表
,
立即开辟空间
#include
using namespace std;
int main(int argc, char *argv[])
{
int a = 10;
const int num = a;
int *p = (int *)#
*p = 11;
cout << "num =" << num << endl;
cout << "*p =" << *p << endl;
return 0;
}
4,
如果
const
修饰的是自定义类变量
,
立即开辟空间
,
不会产生符号常量表
#include
using namespace std;
struct Stu
{
int age;
};
int main(int argc, char *argv[])
{
const Stu s = {18};
//不可直接修改其中的内容
//s.age = 19;
Stu *p = (Stu *)&s;
p->age = 20;
cout << "p->age=" << p->age << endl;
cout << "s.age=" << s.age << endl;
return 0;
}
5,gcc 99/g++11
编译器中
const
修饰的变量可以作为数组创建时的长度
,c
不行
const int x = 10;
int nums[x] = {0};
6,
尽量使用
const
替代无参宏
1,const 有类型,可进行编译器类型安全检查。
#define
无类型
,
不可进行类型检查
2,const 有作用域,而
#define
不重视作用域。
10,引用(重要)
概念
变量名实质上是一段连续内存空间的别名
,
通过变量来命名一片空间
对一段连续的内存空间只能取一个别名吗?
c++
中新增了引用的概念,引用可以作为一个已定义的变量的别名。
引用是
c++
对
c
的重要扩充
,
并不是
c++
的发明。
语法
Type& ref = val;
注意
1,&在此不是求地址运算,而是起标识作用。
2,类型标识符是指目标变量的类型
3,必须在声明引用变量时进行初始化。
4,引用初始化之后不能改变。
5,不能有
NULL
引用。必须确保引用是和一块合法的存储单元关联。
6,可以建立对数组的引用。
示例
1:
认识引用
void test01(){
int a = 10;
//给变量 a
取一个别名
b
cout << "a:" << a << endl;
cout << "b:" << b << endl;
cout << "------------" << endl;
//
操作
b
就相当于操作
a
本身
b = 100;
cout << "a:" << a << endl;
cout << "b:" << b << endl;
cout << "------------" << endl;
//
一个变量可以有
n
个别名
int& c = a;
c = 200;
cout << "a:" << a << endl;
cout << "b:" << b << endl;
cout << "c:" << c << endl;
cout << "------------" << endl;
//a,b,c
的地址都是相同的
cout << "a:" << &a << endl;
cout << "b:" << &b << endl;
cout << "c:" << &c << endl;
}
示例
2:
使用引用的注意事项
void test02()
{
//1)
引用必须初始化
int& ref; //报错
:
必须初始化引用
//2)
引用一旦初始化,不能改变引用
int a = 10;
int b = 20;
int& ref = a;
ref = b; //不能改变引用
//3)
不能对数组直接建立引用
int arr[10];
int& ref3[10] = arr;
}
示例
3:
建立数组引用
void test03()
{
//1.
建立数组引用方法一
typedef int ArrRef[10];
int arr[10];
ArrRef& aRef = arr;
for (int i = 0; i < 10;i ++){
aRef[i] = i+1;
}
for (int i = 0; i < 10;i++){
cout << arr[i] << " ";
}
cout << endl;
//2.
建立数组引用方法二(建议直接记第二种)
int(&f)[10] = arr;
for (int i = 0; i < 10; i++){
f[i] = i+10;
}
for (int i = 0; i < 10; i++){
cout << arr[i] << " ";
}
cout << endl;
}
示例
4:
建立指针变量的引用
int num = 10;
int *p = #
int *&myP = p;
cout<<"*myP = "<< *myP<< endl;
示例
5:
给函数取别名
void fun01(void)
{
cout << "fun01" << endl;
}
int main(void)
{
int (&p)(void) = fun01;
p();
}
函数中的引用
引用作为形参
当函数中的形参是引用时,
是地址传递
,
类似与指针
引用作为函数的参数优点:
1、实参不用取地址
2、引用(形参)不会另辟空间(不占空间)
3、函数内部 不需要指针解引用
示例:
void test04(int& x)
{
x = 10;
}
int main(int argc, char *argv[])
{
int num = 1;
test04(num);
cout << "num=" << num << endl;
return 0;
}
引用作为返回值
当函数中的返回值为引用时
.
要确保当函数执行完毕后
,
引用关联的内存一定要存在
示例
:
函数不要返回局部变量的引用
int& test05()
{
static int x = 10;
int& p = x;
return p;
}
int main(int argc, char *argv[])
{
int& num = test05();
cout << "num = " << num << endl;
return 0;
}
示例
:
链式编程
struct person
{
char name[50] = {0};
person& eat = (person &p,char *foodname);
{
cout << p.name << "吃" << foodname << endl;
return p;
}
};
void fun()
{
person *p = "zhangsan";
p.eat(p,"油泼面").eat(p,"油泼面").eat(p,"油泼面“);
}
常引用
概述
概念:
常量的引用
特点:
值不能被修改
示例
void test07(void)
{
const int& num = 10;
num = 11;//err
不能被修改
}
作用
:
防止函数内部 通过引用修改外部的值
优点
:
引用不产生新的变量,减少形参与实参传递时的开销。
由于引用可能导致实参随形参改变而改变,将其定义为常量引用可以消除这种副作用。
如果希望实参随着形参的改变而改变,那么使用一般的引用
如果不希望实参随着形参改变,那么使用常引用
void showData(const int &data)
{
//data = 2000;//err
cout<<"data = "<
}
void test08()
{
int num = 100;
showData(num);
cout<<"num = "<
}
11,内联函数(了解)
概念
:
由关键字
inline
修饰的函数 为内联函数。
inline void add(int a,int b)
{
cout << a+b << endl;
}
int main()
{
//add(10,2);
cout << 10+2 << endl;
}
特点:
内联函数:在编译阶段像宏一样展开。有作用域的限制(作为类的成员函数)。
内联函数为了继承宏函数的效率,没有函数调用时开销,然后又可以像普通函数那样,
可以进行参数,返回值类型的安全检查,又可以作为成员函数。
注意:
1,inline只能在定义函数的时候修饰。
2,任何在类内部定义的函数自动成为内联函数。
3,inline修饰的函数是否为内联函数,取决于编译器。对于非
inline
修饰的函数,也
有可能转成内联函数(体积小、功能简单的函数)。
内联条件:
不能存在任何形式的循环语句
不能存在过多的条件判断语句
函数体不能过于庞大
不能对函数进行取址操作
宏函数和内联函数区别(重要)面试题
宏函数:
参数没有类型,
不能保证参数的完整型。
宏函数 在预处理阶段展开。
宏函数 没有作用域限制 不能作为类的成员。
内联函数:
参数有类型 保证参数的完整型。
内联函数 在编译阶段 展开。
内联函数 有作用域限制 能作为类的成员
示例:
inline void test09(int a,int b)
{
cout << a+b << endl;
}
12,形参的默认值
特点
c++在声明函数原型的时可为一个或者多个参数指定默认
(
缺省
)
的参数值,当函数 调用
的时候如果没有指定这个值,编译器会自动用默认值代替
注意
如果某形参设置了默认参数,那么这个形参的右方所有形参都必须设置默认参数
示例:
void test10(int a = 1,int b = 10)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
}
int main(int argc, char *argv[])
{
test10();
return 0;
}
void test10(int a=1,int b)//err
cout << "a = " << a << endl;
cout << "b = " << b << endl;
int main(int argc, char *argv[])
13,占位参数
概念
只有形参类型 没有形参名的参数 叫占位参数。
示例
void test11(int a,int)
{
cout << "a = " << a << endl;
}
void test12(int a,int=10)
{
cout << "a = " << a << endl;
}
int main(int argc, char *argv[])
{
test11(1,2);
return 0;
}
注意
占位参数 重载++ --
运算符才用。
14,函数重载
函数重载 是静态多态。
函数重载:一个函数名 多个函数功能。
函数重载的条件:同一作用域,函数的参数个数、类型、顺序不同都可以重载,返回值类
型不能作为重载条件。
示例
void test13()
{
cout << "test13-01" << endl;
}
void test13(int i)
{
cout << "test13-02" << endl;
}
void test13(int i,char c)
{
cout << "test13-02" << endl;
}
c++,
函数名和参数 一起决定函数的入口地址
底层原理
注意
:
因为
c++
在编译函数时会在函数名前随机添加新的名称所以此时
test13
函数将生成
以下函数名
如
_Z4test13v //v
代表无返回值
_Z4test13i //i
为参数类型的首字母
_Z4test13ic //i
为第一个参数类型的首字母
,c
为第二个参数类型的首字母
注意:
//
函数重载和缺省参数 在一起 容易产生二义性
void test14(int a)
{
cout << "test14-01" << endl;
}
void test14(int a,int b=10)
{
cout << "test14-01" << endl;
}
15,混合编程
由于
c++
可以使用
C
的模块中函数,当
C++
整个工程编译时,可能会将使用
C
语言编写的函
数名编译成
c++
规则的函数名(定义的函数名前随机添加新的名称),链接程序时,可
能会找不到目标函数,因此采用
extern "C"
解决。
错误演示:
//test.h
#ifndef TEST_H
#define TEST_H
extern void test(int x);
#endif // TEST_H
//test.c
void test(int x)
{
}
//main.cpp
#include
#include "test.h"
using namespace std;
int main(int argc, char *argv[])
{
test();
return 0;
}
修改
//test.h
#ifndef TEST_H
#define TEST_H
#ifdef __cplusplus
extern "C"{
#endif
extern void test(int x);
#ifdef __cplusplus
}
#endif
#endif // TEST_H