一、C++中的命名空间
C++中使用命名空间来解决在相同文件或范围的同名变量问题,示例程序如下:
#include <iostream>
using namespace std;
#if 0
int g_count = 100;
int g_count = 200; //error,重命名错误
#endif
namespace stuname //定义命名空间stuname
{
const char *name = "zhangsan"; //定义命名空间中stuname的变量name
}
namespace homename //定义命名空间homename
{
const char *name = "xiaozhang"; //定义命名空间中homename的变量name
}
int main()
{
cout << "school : " << stuname::name << endl; //访问stuname命名空间中的数据
cout << "homename : " << homename::name << endl; //访问homename命名空间中的数据
}
二、C++标识符声明使用的三种方法
C++的所有标识符都被定义在一个名叫std的namespace(命名空间)里,要想使用这些标识符,则必须先声明,声明有以下3种方法:
int main()
{
#if 0 //第1种:直接声明使用
std::cout<<"hello world"<<std::endl;
#endif
#if 0 //第2种:先用using声明要使用的标识符
using std::cout;
using std::endl;
cout<<"hello world"<<endl;
#endif
#if 1 //第3种:声明使用标准命名空间中所有内容(即标识符)
using namespace std; //一般申明在头文件后
cout<<"hello world"<<endl;
#endif
return 0;
}
三、自动类型转换的四种情况
在C/C++中有以下四种情况会发生自动类型转换:
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
int add(double num1,double num2)
{
return num1+num2;
}
int main()
{
//第1种:赋值
int i = 3.14; //转换成int型
cout << "i=" << i << endl;
//第2种:运算时
double res = 4 + 3.14; //4运算前转换成double型
cout << "res=" << res << endl;
//第3种: 函数调用实参与形参不一致时,自动转换成形参类型
//第4种:当返回值类型与函数返回类型不一致时,自动转换成函数返回类型
int result = add(2,3); //2,3转换成double型,5再转换成int型
cout << "result=" << result << endl;
return 0;
}
四、引用的使用
引用就是某一变量(目标)的一个别名,对引用的操作与对变量的直接操作完全一样。
引用的声明方法:类别标识符 **&**引用名 = 目标变量名。
示例程序如下所示:
int a;
int &ra=a; //定义引用ra,它是变量a的引用,即别名。
说明:
- &在此处不是取地址运算,而是标识作用。
- 声明引用时,必须对其进行初始化。
- 引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量的别名。
- 声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,他本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。因此对引用求地址,就是对目标变量求地址。
- 不能建立数组的引用,因为数组是一个由若干个元素组成的集合,所以无法建立一个数组的别名。
五、C++内联函数
C++中支持内联函数,其目的是为了提高函数的执行效率,使用关键字 inline 可将函数指定为内联函数,内联函数通常就是将它在程序中的每个调用点上“内联地”展开,假设我们将 max 定义为内联函数:
inline int max(int a, int b)
{
return a > b ? a : b;
}
调用: cout<<max(a, b)<<endl;
,在编译时展开为: cout<<(a > b ? a : b)<<endl
;从而消除了把 max写成函数的额外执行开销。
C++ 语言的函数内联机制既具备宏函数的效率,又增加了安全性,而且可以自由操作类的数据成员。所以在 C++ 程序中,应该用内联函数取代所有宏函数,“断言 assert”恐怕是唯一的例外。
注意
- 代码过长,多于3行,则编译器会忽略 inline 限定符。
- 在类定义中的定义的函数都是内联函数,即使没有使用 inline 说明符。
- 函数内不能有复杂结构,例如for循环和开关语句。
六、C++多态相关
1、虚函数声明如下:virtual ReturnType FunctionName(Parameter) 虚函数必须实现,如果不实现,编译器将报错,错误提示为:
error LNK****: unresolved external symbol "public: virtual void __thiscall ClassName::virtualFunctionName(void)"
2、虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。
3、在有动态分配堆上内存的时候,析构函数必须是虚函数,但没有必要是纯虚的。且基类的析构函数必须是虚函数,否则会析构不完全。
4、友元不是成员函数,只有成员函数才可以是虚拟的,因此友元不能是虚拟函数。但可以通过让友元函数调用虚拟成员函数来解决友元的虚拟问题。
5、C++多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数;形成多态必须具备三个条件:
- 必须存在继承关系;
- 继承关系必须有同名虚函数(其中虚函数是在基类中使用关键字Virtual声明的函数,在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数);
- 存在基类类型的指针或者引用,通过该指针或引用调用虚函数;
6、父类的虚函数或纯虚函数在子类中依然是虚函数。有时我们并不希望父类的某个函数在子类中被重写,在 C++11 及以后可以用关键字 final 来避免该函数再次被重写。
例:
#include<iostream>
using namespace std;
class Base
{
public:
virtual void func()
{
cout<<"This is Base"<<endl;
}
};
class _Base:public Base
{
public:
void func() final//正确,func在Base中是虚函数
{
cout<<"This is _Base"<<endl;
}
};
class __Base:public _Base
{
/* public://不正确,func在_Base中已经不再是虚函数,不能再被重写
void func()
{
cout<<"This is __Base"<<endl;
}*/
};
int main()
{
_Base a;
__Base b;
Base* ptr=&a;
ptr->func();
ptr=&b;
_Base* ptr2=&b; ptr->func();
ptr2->func();
}
/*
输出结果:
This is _Base
This is _Base
This is _Base
*/
如果不希望一个类被继承,也可以使用 final 关键字。
格式如下:
class Class_name final
{
...
};
则该类将不能被继承。
七、C++ 函数传递参数的三种方式
(1)值传递
当进行值传递时,就是将实参的值复制到形参中,而形参和实参不是同一个存储单元,所以函数调用结束后,实参的值不会发生改变。程序示例如下:
#include <iostream>
using namespace std;
void swap(int a,int b)
{
int temp;
temp=a;
a=b;
b=temp;
cout<<a<<","<<b<<endl; // 2,1
}
int main()
{
int x=l;
int y=2;
swap(x,y);
cout<<x<<", "<<y<<endl; // 1,2
return 0;
}
(2)指针传递
当进行指针传递时,形参是指针变量,实参是一个变量的地址,调用函数时,形参(指针变量)指向实参变量单元。这种方式还是 “值传递”,只不过实参的值是变量的地址而已。而在函数中改变的不是实参的值,而是实参地址所指向的变量的值。程序示例如下:
#include <iostream>
using namespace std;
void swap(int *a,int *b)
{
int temp;
temp=*a;
*a=*b;
*b=temp;
cout<<*a<<","«*b«endl; // 2,1
}
int main()
{
int x=l;
int y=2;
swap(&x,&y);
cout<<x<<","<<y<<endl; 2,1
return 0;
}
也就是说,在进行函数调用时,不仅交换了形参的值,而且交换了实参的值。
(3)引用传递
实参地址传递到形参,使形参的地址取实参的地址,从而使形参与实参共享同一单元的方式。程序代码示例如下:
#include <iostream>
using namespace std;
void swap(int &a,int &b)
{
int temp;
temp=a;
a=b;
b=temp;
cout<<*a<<","<<*b<<endl; // 2,1
}
int main()
{
int x=l;
int y=2;
swap(x,y);
cout<<x<<","<<y<<endl; // 2,1
return 0;
}