关键字在类中的扩展
C++引入的面向对象的概念之后,C 语言中的一些比如 static/const 等原有语意,作一些升级处理,此时既要保持兼容,还要保持不冲突。
类成员存储
sizeof
#include <iostream>
using namespace std;
class Time
{
public:
void dis()
{
cout<<hour<<minute<<sec<<endl;
}
private:
int hour;
int minute;
int sec;
};
int main()
{
cout<<sizeof(Time)<<endl; //12
//一个对象所占的空间大小只取决于该对象中数据成员所占的空间,而与成员函数无关
return 0;
}
类成员函数的可能存储方式
用类去定义对象时,系统会为每一个对象分配存储空间。如果一个类包括了数据和
函数,要分别为数据和函数的代码分配存储空间。
按理说,如果用同一个类定义了 10 个对象,那么就需要分别为 10 个对象的数据
和函数代码分配存储单元。
类成员函数的实际存储方式
能否只用一段空间来存放这个共同的函数代码段,在调用各对象的函数时,都去调
用这个公用的函数代码。
显然,这样做会大大节约存储空间。C++编译系统正是这样做的,因此每个对象所
占用的存储空间只是该对象的数据部分所占用的存储空间,而不包括函数代码所占用的
存储空间。
那么这里有个疑问,当对象调用公用函数时,如何确定,访问的成员是调用对象的
成员呢?
因为this指针
C++设置了 this 指针,对象在调用公用函数时,并将对象的指针作为隐含参数传
入其内,从而保证了访问的成员,属于调用者
#include <iostream>
using namespace std;
class Time
{
public:
Time(int h, int m,int s)
:hour(h),minute(m),sec(s){}
void dis() //void dis(Time *p)
{
cout<<"this="<<this<<endl;
cout<<this->hour<<":"<<this->minute<<":"<<this->sec<<endl;
}
private:
int hour;
int minute;
int sec;
};
int main()
{
Time t(1,2,3);
Time t2(2,3,4);
t.dis(); //等价于 t.dis(&t)
t2.dis();
return 0;
}
输出:
this=0x3f987ff9d4
1:2:3
this=0x3f987ff9c8
2:3:4
const 修饰成员变量
const 修饰数据成员,称为常数据成员,可能被普通成员函数和常成员函数来使
用,不可以更改。
必须初始化,可以在类中(不推荐),或初始化参数列表中(这是在类对象生成之前
唯一一次改变 const 成员的值的机会了)。
初始化列表,一方面提高了效率,另一方面解决一类因面向对象引入的一些新功能
的特殊安排。
#include <iostream>
using namespace std;
class A
{
public:
A(int i):_ci(i)
{
}
void dis()
{
cout<<_ci<<endl;
}
private:
const int _ci = 100;
};
int main()
{
A a(200);
a.dis();
return 0;
}
const 修饰函数
const 成员函数的意义在于, 承诺在本函数内部不会修改类内的数据成员,为此,也只能调用承诺不会改变成员
的 const 成员函数,不会调用其它非 const 成员函数。
#include <iostream>
using namespace std;
class A
{
public:
A(int i):_ci(i),_x(10),_y(100){}
void dis()
{
cout<<_ci<<endl;
}
//const 修饰函数,承诺在本函数内部不会修改类内的数据成员,
void dis() const
{
cout<<_ci<<endl;
cout<<_x<<endl;
cout<<_y<<endl;
//_x = 1; //err
// _y = 2; //err
//print(); //err
}
//改成void print() const 则在dis可被调用了
void print()
{
}
private:
const int _ci = 100;
int _x;
const int _y;
};
int main()
{
A a(200);
a.dis();
return 0;
}
const 修饰函数且重载
有const 构成的重载函数,非const对象,优先调用的是非const版本的函数
const的对象,只能调用const版本的函数,很多库会提供两个版本
const
1 const 修饰函数,在声明之后,实现体之前。
2 const 函数只能调用 const 函数。非 const 函数可以调用 const 函数。
3 如果 const 构成函数重载,const 对象只能调用 const 函数,非 const 对象优先调
用非 const 函数。
4 类体外定义的 const 成员函数,在定义和声明处都需要 const 修饰符。
有些关键字是定义型的,有些是声明型的。
const 修饰对象
const 修饰对象,保证在对象层面不会修改数据成员。所以 const 对象,只能调
用 const 成员函数。不同编译器,可能会要求必须自实现构造器,因为若采用默认的
话,const 对象的中成员,再无初始化的机会。
#include <iostream>
using namespace std;
//const修饰的对象之中可以有非const成员,但不可修改,只能调用const成员函数,
//针对对象可能会被const修饰,一般会提供两个版本,构成重载,以便于对象传递到其他函数,其他函数可以调用非const版本的函数
class A
{
public:
A(int x,int y):_x(x),_y(y){}
void dis() {
}
void dis() const{
}
private:
int _x;
int _y;
};
int main()
{
const A a(100,200);
a.dis(); //调用一个不被const修饰的函数,就会报错,,void dis() const就不会报错了
return 0;
}