c++基础知识
文件扩展名
不同编译器扩展名不同,一般为.cpp,.cxx,.cc
注释
//为当前段内的注释
/**/可以跨段注释
命名空间
即为函数库(iostream.h,stream.h…)
声明:
namespace A
{
int x;
void fun(){…};
}
访问:
当定义了以上A时,可采用两种方式访问
- A::x;A::fun();
- using namespace A;
A;
示例:
using namespace std;
cout<<“oh!”<<endl;
或:
std::cout<<“oh!”<<std::endl;
此外,命名空间允许嵌套,此处不做赘述
输入输出
- 输出:cout<<“oh!”;cout<<“oh!”<<endl;
- 输入:cin>>a>>b;输入两个数时,用空格间隔开
变量定义
c++支持在程序任何地方定义变量,而不需要像C一样必须在开始定义,但变量的定义必须在函数的调用之前
强制类型转换
格式:数据类型(表达式)
例:int x;char(x)
**注意:**这种转换只产生一个中间变量,并不改变原变量的类型,如以上示例,转换后x依旧为 int 类型。
动态内存(new delete)
- 分配
C:A=(int *)malloc(sizeof(int));
C++:A=new int;(A为int指针) - 释放
C:free(A);A为数组时:需写循环逐个释放
C++:delete A;A为数组时:delete []A;
作用域运算符(::)
当全局变量与局部变量同名时:
例:
int a=10;
void main()
{
int a=5;
cout<<a;
cout<<::a;
}
未加::时,访问局部变量,加::后,访问全局变量
引用符(&)
- 引用
格式:数据类型&引用变量名=变量名;
例:
int b=10;
int&a=b;//int& a=b,int &a=b,int & a=b均是正确格式
对引用进行操作,实际上就是对被引用的变量进行操作。(如:张三小名叫三三,那我叫张三去提水,和叫三三去提水是一样的。)引用不是值,不占存储空间。引用一旦被初始化,就不能重新赋值。
- 取地址符
int a=10;
int *p=&a;
此时&表示取a的地址,赋予给指针p
const
- C定义常量:#define pi 3.14
- C++定义常量:const int pi=3.14
c++常量多了数据类型
const的三种情况
- const char *p=“abcd”
其中
"abcd"为常量,*p为指向它的指针;*p可以改变指向地址,而"abcd"不能改变 - char const *p=“abcd”
其中
*p为常量指针,"abcd"为值;p指向的地址不能变,但p指向的内容"abcd"可以变 - const char const *p=“abcd”
其中
*p为常指针,"abcd"为常量,均不能改变
字符串(string)
string为C++新增类型,存储字符串,C中只能用数组实现
例:
string a=“oh!you found me”;
string不用写长度,也不会溢出
函数
内联函数(略)
带默认参数的函数
定义函数时,可以指定形参的值,当调用函数却没给出参数值时,便调用默认的值(定义时指定的值)
例:
void A(int a=10){cout<<a;}
void main()
{
A();
}
以上函数调用默认值a=10
限制规则
默认参数必须由右向左依次连续给出,调用函数时,缺省的值也必须在右边
例:
void A(int a,int b,int c=10,int d=40){cout<<a;}//a,b没有默认值
void main()
{
A(10,20,30,40);//缺d的值,调用默认值40
}
函数重载
即:C++允许多个函数有一样的函数名,程序自动寻找符合条件的函数调用
例:
void A(int a){…};
void A(int a,int b){…};
void main()
{
A(10,20);//自动调用第二个函数
}
注意:
- 若两个函数参数个数与类型都相同,仅返回值不同,不允许重载
- 函数重载与带默认值的函数一起使用时,会引起二义性
例:
void A(int a){…};
void A(int a,int b=10){…};
void main()
{
A(10);//报错
}
类和对象
类
类的定义例:
class A
{
private:
......
public:
.......
protected:
.........
}
类的访问权限:分为三类:private(私有,默认为私有)public(公有)protected(保护)
类与结构体区别:结构体为C语言所用,内部只有参数,而结构体为C++所用,内部有参数与函数
注意:
- 定义类时,不允许初始化数据成员
- 类定义时,不要丢掉结束标志“;”
成员函数定义
外联成员函数
例:
class A
{
void show(int a);
}
void A::show(int a)
{
cout<<a;
}
即将函数内容放在类外
内联成员函数
方式一:
class A
{
void show(int a) {cout<<a;};
}
方式二:
class A
{
inline void show(int a);
}
inline void A::show(int a)
{
cout<<a;
}
注意:C++文件的多文件结构
1.将类的声明放在头文件.h中
2.将类中的外联函数,放在.cpp文件中
3.调用函数时,记得包含头文件(#include)
对象(即实例)
对象的定义
方法一:
class A
{
public:
int number;
void show(int a);
} student,teacher;
`
方法二:
```cpp
class A
{
void show(int a);
}
A student,teacher;
成员的访问
方法一:对象一.公有成员;(*指针).公有成员
例:A.number
方法二:指针:指针->公有成员
例:
p->number
**注意:**私有成员外部无法访问,只能通过该类的公有成员函数来访问
this指针
this指针是类中隐藏的指针,常见用法:
class A
{
int number;
public:
A(int number){this->number=number;};
}
带缺省成员函数,重载成员函数
与全局函数规则相同,此处略过
构造函数与析构函数
构造与析构函数特点:
- 他们都没有返回值说明,即不能指出函数返回值类型(包括void)
- 不能被继承(详见后面的继承)
- 构造函数可以有缺省参数
- 析构函数可以为虚函数(virtual),但构造函数不行
- 不可取他们的地址
- 不能用常规方法调用构造函数
- 定义对象时,自动调用构造函数;删除对象(程序结束)时,自动调用析构函数
构造函数
构造函数是一个与类同名,没有返回值的特殊成员函数。即可类内定义,也可类外定义,允许带有默认参数,也允许缺省参数
例:
class student
{
int num;
int math;
public:
student(int num,int math);//构造函数声明
}
student::student(int num,int math)//构造函数定义
{this->num=num;this->math=math;}
void main()
{
student A(0,100);//定义时自动调用,给对象赋初值
}
- 功能:初始化定义的对象(即给新定义的对象赋初始值)
- 声明格式:与普通类内函数相同
- 可否重载:可以,但形参个数,类型不能完全相同(重载规则)
- 访问类型:一般为public。private时只能在本类和友元中创建
注意:默认构造函数(缺省构造函数)与对象数组
默认构造函数
定义:当没有声明构造函数时,C++提供一个默认构造函数(也叫缺省构造函数)
功能:默认构造函数是没有参数的函数,仅负责创建对象,不负责初始化工作(即不赋初始值)
只要定义了构造函数,c++就不提供默认构造函数,想要使用默认构造函数,需自己定义(利用重载)
构造函数调用顺序:虚基类>非虚基类>>对象成员>>派生类
析构函数
析构函数名:~类名
例:
class student
{
int num;
public:
student(int nu){num=nu};
~student();//析构函数
}
功能:与构造函数相反,当对象被撤销时,释放该对象占有的空间
可否重载:不能,每个类只有一个析构函数,且析构函数中没有参数
析构函数调用:
- 对象删除时,系统自动调用
- 手动调用:对象名.类名::析构函数
析构函数与构造函数调用顺序
先构造的后析构
拷贝函数
类含有默认的拷贝函数(为浅拷贝)
功能:用一个类初始化另一个类
特点:形参是本类对象的引用,拷贝函数是特殊的构造函数(没有类型)
声明形式:类名(类名 & 对象名)
例:
class student
{
构造函数....
student(student &person1);//拷贝函数声明
}
student::student(student &person1)//拷贝函数的定义
{
......
}
自动调用拷贝函数情况:
- 用一个类初始化另一个类
student s1;
student s2(s1);
student s3=s1;
- 将对象作为参数传递时
founction(student a){};
student stu1;
founction(stu1);
- 函数返回值为对象
founction()
{
student A;
return A;
}
student B;
B=founction();
深拷贝与浅拷贝
浅拷贝:只复制对象空间,不复制对象资源
深拷贝:既复制对象空间,也复制对象资源
当浅拷贝的类中,含有指向对象的指针时,拷贝后的类中的指针依旧指向同一个地址。
深拷贝时,指针指向两个不同的地方。
满足以下所有条件时,必须定义深拷贝函数
- 肯定要调用拷贝函数
- 数据成员包含指向堆内存的指针
对象成员
即类对象作为另一个类的数据成员
例:
class A{}
class B
{
A stu1;
}
构造函数例:
class student
{
int number
public:
A stu1;
student(int num,char name):stu1(name){number=num;}//函数体只写新增的元素,构造函数参数表需写全部的参数,其后的参数表不用写参数类型。
}
在执行构造函数时,先调用对象成员的构造函数,再调用该类的构造函数;
在执行析构函数时,执行顺序相反。即先调用析构函数,再调用对象成员析构函数。
静态成员
静态数据成员声明及类外初始化:
static int x;声明格式
int A::x=5;初始化
静态成员函数声明:
static void func();声明
void func(){···};定义
注意:
- 静态成员函数无this指针
- 由于静态函数可以访问该类的所有对象中的成员,在定义时,调用成员的代码需加上前缀,说明调用的是哪个对象的成员(静态成员不用加),见p85
- 静态成员函数不需要创建对象就可以用
- 静态成员函数参数中有类,类的构造函数又有静态成员时,不会改变静态成员的值
友元
友元函数
声明与定义:
class A
{
int score;
public:
A(){...}
friend void show(A& st);
}
void show(A& st)
{cout<<st.A}
注意:
- 友元函数不是类的成员函数,而是类外的普通函数,没有this指针
- 友元函数访问类内成员时,必须加上类名前缀
- 友元函数在public,private,protected中声明效果相同
- 既可在类内定义友元函数,也可在类外定义
- 类外定义时,不需要加friend前缀
友元成员
将另一个类的成员函数声明为某个类的友元
声明方式例:
class A
{
void show(B& st){cout<<st.date;}
}
class B
{
int date;
firiend void A::show(B& st);//声明需加上所属的类前缀,函数类型
}
友元类
将一个类声明为另一个类的友元
例:
class A{
int score;
friend class B;//friend class 类名;
}
class B{...}//B中所有函数可以访问A中的数据,函数