目录
一、const修饰指针的三种情况
二、派生类的的构造函数必须调用基类
三、字符串数组初始化相关问题
四、指针
五、运算符重载
六、string
一、const修饰指针的三种情况
1、const修饰指针 --- 常量指针
const int *p=&a;
记忆:常量+指针 等于常量指针
修饰的是指针,指针指向可以改,指针指向的值不可以更改
2、const修饰常量 --- 指针常量
int *const p=&a;
记忆:*加const 指针常量 要注意一下*的位置
指针的指向不可以改,但指针指向的值可以改
区分以上两者特点的方法:看const 直接修饰的是什么
也就是看const后面跟的东西是什么
对于常量指针 const int *p const后面跟着的是int ,那么就不能对int进行直接操作,也就是不能对于指针指向的值直接操作
对于指针常量 int *const p const后面直接跟着的是p这个指针,那么就不能直接对于指针进行操作,只能对指针指向的值进行修改。
3、const即修饰指针,又修饰常量
const int *const p=&a;
前两者的特征结合
二、派生类的的构造函数必须调用基类
做实验题的时候看某腾木的代码时发现的问题
class person
{
protected:
string name;
int age;
string sex;
public:
person(){}
person(string n,int a,string x):name(n),age(a),sex(x){}
void display()
{
cout<
会发现一个比较奇怪的现象,基类中写了一个根本没有用的无参构造,然而这却是必需的。
首先一个大前提:在派生类调用构造函数初始化对象的时候,必须调用基类的构造函数。
现在来看下派生类中的构造函数是怎么写的
student(string n,int a,string x,int r,string d)
{
name=n; age=a; sex=x; regnumber=r; department=d;
}
很明显的,这直接在{ }中给所有属性赋了值,而没有使用初始化列表,更别说调用基类的构造函数(这是一种相当图省事的方法)
但基类的构造函数你必须调用,并且这时已经完成了所有属性的赋值,系统不会自动调用基类中编写好的有参构造函数,而是会去寻找无参构造,但很明显,如果你不写无参构造那么基类就没有,就会报错,因此弥补性地写了一个没有任何用处的无参构造函数。
那么平常我们会直接在初始化列表中调用基类的有参构造,这样也不会出现没有调用构造函数的情况,如下:
student(string n,int a,string x,int r,string d):person(n,a,x)
{
regnumber=r; department=d;
}
三、字符串数组初始化相关问题
推荐blog:字符串数组初始化相关问题总结 - Tsingke - 博客园
在这里就提一些我自己比较关注的点
1、字符数组初始化给的初值是‘ ’,而整形数组的初始化初值给0,两个在本身的数组中都默认成NULL
2、初始化字符数组写成char arr[10]="HELLO"
可以近似看作char arr[10]={'H','E','L','L','O'}
但仍然有区别,前者我们看作为利用“字符串”赋初值,而后者是一个“字符”一个“字符”的键入。
对于使用字符串初始化而言,数组的长度必须比你键入的长度要大,因为系统会自动在你初始化完了以后在后面添‘ ’,而如果你使用单个字符赋值就不会出现这样的情况
char arr[5]="China"——————ERROR
而char arr[5]={'C','h','i','n','a'}—--RIGHT
所以要注意字符数组的实际分配的空间大小应该是你输入的字符长度+1,毕竟末尾还有一个' '
当字符数组的实际输入的元素长度没有定义的长度长时,剩下的所有元素都会被系统自动赋上' '
3、对于未知长度的数组,也有计算数组长度的方式(在冒泡排序中我也写过这个问题)
int arr[]={1 ,2,3,5,4,6};
int len =sizeof(arr)/sizeof(int);(或者除以sizeof(arr[0]) )
4、定义数组的场合,数组名可以没有,但数组长度必须有。
省略数组大小只能在 已经有初始化的数组定义之中
5、int array4[5]={ }; //error:语法格式错误
6、这些东西虽然不会在实际理论课上考,但我仍然花了时间去搞,因为对于我而言理解真的挺重要的。
整型数组和字符型数组的输入输出所有注意点,都在这了。
整型数组的输入方式必须通过循环来实现,首先 整型数组的语法中无法像字符数组一样提供首地址后能自动完成所有的输入。
char arr0[10]={' '};
cin>>arr0;
字符数组为什么默认赋' '?是因为作为字符通过ascII转换以后它表示的值也是0,和整型数组其实是一样的,系统会自动将‘ ’作为数值0来处理,所以不管是arr【i】!=0,抑或初始化的时候直接写0,都是可以的
只通过cin直接想字符数组中输入字符,按下回车的那一刻就会停止,系统会自动在后面加一个 ,因此即便你输入的长度没有预定的长,而且没有实现初始化 也没有关系,因为通过cout的方式直接输出,系统会自动检索,直至遇到 ,立刻停止。
如果你在cin的过程中按了一个空格 空格后的内容不再记录于数组中而是会变成下一个cin中的内容
(比如你键入123 456 cout的输出流只会输出123 456会到下一个cin中。
利用循环不断重复输入,而在实际输入的时候只需要输入一个字符 就按一下空格 就是这个道理)
而整型数组必须一个元素一个元素的输入,而要实现这一点就只能够通过i的循环
int arr[10]={0};
for(int i=0;i<10;i++)
{cin>>arr[i];}
当然 整型数组的输出也要通过循环实现
理解重点:
但需要注意的是,直接cout<
而这种遇到 就停的输出方式,也当且仅当你的输出方式是cout<<直接加字符数组首地址
很普通地通过循环来输入输出字符数组中的元素 ,一点问题都没有。(就是输入 也能给你原封不动的输出 )
8、确切先写在这里了,虽然有点偏题。
在基类中声明字符串属性的时候可以只写一个地址。
#include
using namespace std;
class person
{
char *name;
char sex;
int age;
public:
person(char *Name,char Sex,int Age)
{
name=Name;
sex=Sex;
age=Age;
}
void show()
{
cout<<"name:"<
关注一下show()函数,直接cout<
后续代码:
class employee:public person
{
int basicsalary;
int leavedays;
public:
employee(char *n,char s,int a,int salary,int day):person(n,s,a)
{
basicsalary=salary;
leavedays=day;
}
void show()
{
person::show();
cout<<"basicSalary:"<>m_name>>m_sex>>m_age>>m_salary>>m_days;
employee temp(m_name,m_sex,m_age,m_salary,m_days);
temp.show();
return 0;
}
四、指针
1、不管什么类型的指针都是4个字节。
2、指针数组和数组指针
推荐blog:数组指针和指针数组的区别 - jack_Meng - 博客园
这里只说明我自己在实操写代码一开始没看懂的一个地方:
#include
#include
using namespace std;
int main()
{
char *ch[5];
for(int i=0;i<5;i++)
{
ch[i]=new char[10];
cin>>ch[i];
}
定义了一个指针数组以后,ch中存放的每个元素都是一个指针,而这个指针又指向了在堆区中开辟的一个字符空间,ch[i]就是这个空间的首地址,跟直接char ch[10]一个道理,所以之后直接cin>>ch[i]来完成字符串的输入。
至此,实现字符串数组我们就有了两种方式,简单粗暴的string[n]或者定义一个数组指针char *ch[n]。
五、运算符重载
1、重载左移运算符时,即重载左移运算符<<时(其实>>也一样)返回的是ostream&
在这里返回的是引用的理由是:使每次都能够返回cout本身,从而到达正常的输出流中cout可以炼虚运用左移运算符达到输出目的的效果
就比如:cout<
如果返回的不是& 那很明显b是没有办法输出的。
六、string
1、string[n]定义的字符串数组,而不是字符数组



