C++ 语言编译中一些知识点
1编译的步骤和c语言一样
预处理,编译,汇编,连接
1预处理:将所有以#开头的文件展开,头文件,宏定义等
g++ -E xxx.cpp -o xxx.i
2 编译(语法错误的检查)
g++ -S xxx.i -o xxx.s
3汇编(将。s文件变为目标文件(。o),目标文件是二进制文件)
g++ -c xxx.s -o xxx.o
4连接(生产可执行文件)
g++ xxx.o -o xxx
2 C++相比C语言新增内容以及内容上的区别:
1 对于类型的检查更为严格,不同类型之间不可直接赋值,C++不会进行自动强转;
2C中和C++中const的区别
C中:
用const修饰的变量本质上还是一个变量,可以通过指针指向该变量的地址来修改被const修饰的变量的值,不一定要初始化
C++中:
1.被const修饰的变量是真的常量,数组可以使用被const修饰后的常量作为下标,被修饰的变量在定义时一定要初始化
2.const修饰的成员变量:只能初始化(使用初始化列表来初始化),且不能被赋值
3.const修饰的成员方法:
1 成员方法函数里不能修改类对象,
2 const方法不能调用非const方法,
3 可以使用或改变static修饰的变量的值(因为static修饰的变量不属于对象,是类里的变量)
4.const修饰对象时:
1不能通过const对象调用非const的成员方法,可以调用const成员方法,以及系统自动调用的构造函数和析构函数;
2 const对象可以调用static方法;
3 C中和C++中static的区别*
C++中:
1、static修饰成员变量时:不属于类对象,是类的静态成员
2、用static修饰的变量需要在类的外部进行声明定义初始化,类外声明是要加上类名以及作用域的符号;
3、所有的类对象都共享类的static成员;
4、static成员方法没有this指针,只有类对象有this指针
C中:
1、在修饰变量的时候,static修饰的静态局部变量只执行一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放(比真正的全局变量短)。
2、static修饰全局变量的时候,这个全局变量只能在本文件中访问,不能在其它文件中访问,即便是extern外部声明也不可以。
3、static修饰一个函数,则这个函数的只能在本文件中调用,不能被其他文件调用。Static修饰的局部变量存放在全局数据区的静态变量区。初始化的时候自动初始化为0;
4 变量的引用
(取别名):int a =10; int &b = a;
注意:引用不能同时引用两个变量:
地址传递和引用传递的区别:::
地址传递:实参将地址传递给形参,实参形参指向同一片地址空间,形参可以通过间接修改实参的数值,不能直接操作实参所在空间的数据
引用传递:通过引用,将实参取别名,实际操作的就是实参所在的空间地址,可以直接修改该空间的数据
5.函数重载
关键字:同一个作用域下,同一个函数名,参数不同,功能相似
C++允许用同一函数名定义多个函数,这些函数的参数个数和参数类型不同。这就是函数的重载(function overloading)。即对一个函数名重新赋予它新的含义,使一个函数名可以多用。
对于函数重载的个人理解:
同名函数在编译时,如果在C语言中,那一定会报错说某某函数已有主体,但在C++中,C++的编译器有一个变名机制,这个程序员是看不到的,编译器会将同名函数按参数列表的不同,命名为不同的名字,这样在调用时,编译器会根据参数列表来选择要使用的函数。
6 结构体的使用不相同:
C++语法中相对C语法增加了访问权限的概念,有三种:public、private及protected,默认是public。
public:公共成员,表示可以通过结构体变量对象直接访问到成员
private :私有成员,表示仅结构体成员函数可以使用的成员
protected:保护成员,表示被继承的派生对象可以访问使用的成员
7 namespace
C++中对名字空间的调用:
声明:using namespace +名字空间的名字 或者 名字空间的名字::也可以表示声明
作用:写程序时如果两个人写的库文件中出现同名的变量或函数(不可避免)
,使用起来就有问题了。为了解决这个问题,引入了名字空间这个概念。
#include
namespace space1{ //名字空间1
int i = 10;
void func1()
{
cout << “i = “ << i << endl;
}
};
namespace space2{ //名字空间2
int i = 20;
void func2()
{
cout << “i = “ << i << endl;
}
};
int main()
{
using namespace space1; //当名字空间里函数名不相同时,可以通过此声明来直接调用空间内的函数;如果函数名相同,就不能用该声明来调用,因为两个空间同时声明在同一作用域,在调用时会有冲突;
func1();
using namespace space2;
func2();
/***在同一作用域下如果函数同名,可以通过下面这种来调用/
space1::
func();
space2::
func();
return 0;
}
}
8 类型强转:
C中:(数据类型)+ 表达式;------int a; char ch = (char)a
C++中:数据类型 +(表达式);-------int a; char ch = char(a)
9 动态内存:
Malloc–free:malloc是一个函数
New—delete:new是一个运算符
10 标准输入输出流
头文件:#include
使用时要先声明:using namespace std;
1 标准输入:
一般表达式:
cin >> 表达式1 >> 表达式2..... >> endl;
2 标准输出:
一般表达式:
cout << 表达式1 << 表达式2。。。。<< endl;
11 类和对象
1 类是对象的抽象,而对象是类的具体实例
2 类是抽象的,不占用内存,而对象是具体的,占用存储空间。在一开始时弄清对象和类的关系是十分重要的
3 类定义的形式:
class 类名
{
private:
私有的数据和成员函数(又可以叫成员方法、访问接口);
public:
公用的数据和成员函数;
protected:
保护的数据和成员函数
};
类的构造和析构函数:
构造函数的一般形式:
类名(数据类型 形参1 = 初始值,数据类型2 形参2 = 初始值):成员变量名(变量名); // 在构造对象时自动调用构造函数,并初始化
构造函数:1 与类名同名,不能随便定名字;
2 没有返回值
3 不需要用户来调用,系统会在构造对象是自动调用,构造函数的功能是由用户定义的,用户根据初始化的要求设计函数体和函数参数
4 如果用户不定义构造函数,系统会提供默认的构造函数
5 只会在构建对象的时候调用构造函数
析构函数:
定义:是在一个对象的生命期即将结束的时候,应该回收该对象占有的资源,或是完成一些清理工作。
特点:
1 析构函数既没有返回值,也没有函数参数,因此它不能被重载。
2 析构函数的语法一般是在类名前加一个“~“。
3 当对象消亡的时候析构函数会自动被调用。
4 可以显示调用析构函数。
析构函数的一般形式
~类名(){}
12 浅拷贝和深拷贝函数
浅拷贝:没有开辟新的内存空间,只是将数值拷贝了一份。
Damo obj2(obj); //默认的拷贝构造函数(浅拷贝),第一种情况,一般格式的拷贝,用一个已经构建的对象作为参数,去构建另一个对象;
Damo *p = new demo(obj); //第二种情况,动态的创建对象,通过指针,new运算符以及指定的对象作为蓝本来构建新的对象;
void test1(Demo &obj)
{
cout << obj.getval() <<endl;
}
test1(obj); //第三种情况,通过函数传参来实现对象的拷贝,三种情况都是隐式调用,如果没有自己定义的拷贝函数,则自动调用默认的拷贝函数;
Damo obj4(obj); //自定义拷贝构造函数(没有开辟新的空间,浅拷贝);
深拷贝:重新开辟了一片空间,用来构造对象,并保存蓝本对象中的数据。
lass damo{
public:
damo(int len) //构造函数
{
num = len;
char *p = new char[num];
assert(NULL != p);
for(int i = 0;i < num;i++)
{
p[i] = i;
}
cout << LINE << endl;
}
~demo()
{
}
public:
/***深拷贝构造函数/
demo( demo &other)
{
this->num = other.num;
this->p = new char[num]; //重新开辟空间,用来存储other对象中的数据
for(int i = 0;i < num ;i++)
{
p[i] = other.p[i];
}
cout << “success…” << endl;
}
private:
int num;
char *p;
};
int main()
{
damo obj(20);
damo obj2(obj);
return 0;
}
12 友元:
特点:不能继承,单向的(没有交换性),不具有传递性
三种友元:
1友元函数:
通过在类中声明:
Friend + 函数;
这个不属于类更不属于对象,但可以直接访问类中的私有变量(所以成员都可以直接访问);
友元函数 的调用方法和普通函数一样;
2友元成员函数
通过在一个类中声明另一个类中的成员函数来直接访问第一个类中的所有成员(包括私有成员),这里的声明和定义是有顺序的; 类的前项声明:class +类名;
3友元类
声明:
friend class 类名;
定义:
一个类是另一个类的友元 ,友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。
13 运算符重载:
作用:让自定义类型的变量,比如对象,能够像基本类型变量一样进行运算,需要对运算符重载;
一般形式:
返回值类型 operator 运算符 (形参列表)
{
函数体
}
不可重载的运算
一共五种:. ?: sizeof :: *
“?:”(三目条件运算符)
“.”(成员访问运算符)
“::”(作用域运算符)
“sizeof”(计算长度运算符)
“->”和“.” (成员指针访问运算符)