static
c
static在c中是一个多义词,可修饰全局对象和局部对象
- 修饰全局对象:对应中文为"内部的",修饰对象作用域
- 修饰局部对象:对应中文为"静态的",修饰对象存储方式(生命周期)
static全局对象
static int g_static_food = 5; //static全局数据对象定义
static void feed(int rice, int meat); //static全局函数对象声明
static void feed(int rice, int meat) { printf("feed rice and meat\n"); } //static全局函数对象定义
static局部对象
void feed()
{
static int l_static_food = 5; //static局部数据对象定义
}
c++
c++对c static功能进行了保留,并未做任何改变,但扩展了static功能,扩展的static功能主要用于:
- static数据成员:不属于this成员
- static函数成员:无this隐含参数
class CAnimal
{
private:
static int totalGroup;
public:
static int getTotalGroup();
};
int CAnimal::totalGroup = 5;
int CAnimal::getTotalGroup()
{
return totalGroup;
}
const
c
const对象可不初始化,未初始化的const对象值无意义(无值且值不可修改)
c之所以允许const对象可不初始化(未初始化的const对象值无意义)是因为struct(union)无构造函数,如果const对象必须初始化且struct(union)有const成员对象,则必须对整个struct(union)对象初始化,这与普通对象(普通成员对象)可不初始化矛盾,因此const对象可不初始化是c的无奈妥协
struct Animal
{
int age;
int color;
const int food;
};
void use_const()
{
int const ci;
int* const cpi;
struct Animal animal;
printf("ci = %d\n", ci);
printf("cpi = %p\n", cpi);
printf("animal.age = %d, animal.color = %d, animal.food = %d\n", animal.age, animal.color, animal.food);
}
output:
ci = 1606416504
cpi = 0x12068
animal.age = 73832, animal.color = 512, animal.food = 515
注:const对象与普通对象一样,未初始化无值(非默认0值)
c++
const对象必须初始化,因为class(struct&union)含构造函数,构造函数是初始化行为,如果class(struct&union)含const数据成员对象,可通过构造函数初始化
const对象必须初始化保证了const对象值有意义(初值且值不可修改)
void use_const()
{
int i = 5;
//int const ci1;
int const ci2 = i;
//int* const cpi1;
int* const cpi2 = &i;
printf("ci = %d\n", ci2);
printf("cpi = %p\n", cpi2);
}
修饰引用
引用本质是const对象,类型为指针,const引用的const修饰引用的类型,因此const引用本质是const对象,类型为const指针(指向const对象)
- int& ri等价于int* const ri
- const int& rci等价于 const int* const rci
void const_ref()
{
int i = 5;
const int ci = 8;
int& ri1 = i;
//int& ri2 = ci;
const int& rci1 = i;
const int& rci2 = ci;
}
const修饰类
const修饰类,可修饰类的部分有:
- non-static数据成员:必须在构造函数显式初始化,即在构造函数初始化列表的初始化式中显式初始化,不能进行默认初始化(不能omit),自此const non-static数据成员不可修改
- non-static函数成员:const修饰this,常规this类型为classname* const this,const修饰后为classname const* const this,因此不可修改实例对象this数据成员(non-static数据成员,属于this成员),不可调用non-static函数成员(this传递时,classname const*不能转classname*)
- static数据成员:不可修改staitc数据成员
class CFood
{
public:
int foodid;
public:
CFood() : foodid(0) { cout << "CFood()" << endl; }
public:
CFood(int fid) : foodid(fid) { cout << "CFood(int)" << endl; }
public:
~CFood() { cout << "~CFood()" << endl; }
};
class CAnimal
{
private:
int const cColor;
int color;
private:
CFood const cFood;
CFood food;
public:
CAnimal();
public:
~CAnimal();
public:
void init() const;
public:
void info();
private:
static int const totalGroup;
public:
static int getTotalGroup();
};
int const CAnimal::totalGroup = 5;
CAnimal::CAnimal() : cColor(5), cFood(5)
{
//cColor = 5;
color = 8;
//cFood.foodid = 5;
food.foodid = 8;
//totalGroup = 58;
cout << "CAnimal()" << endl;
}
CAnimal::~CAnimal()
{
//cColor = 5;
color = 8;
//cFood.foodid = 5;
food.foodid = 8;
//totalGroup = 58;
cout << "~CAnimal()" << endl;
}
void CAnimal::init() const
{
//cColor = 5;
//color = 8;
//cFood.foodid = 5;
//food.foodid = 8;
//totalGroup = 58;
cout << "init()" << endl;
}
void CAnimal::info()
{
//cColor = 5;
color = 8;
//cFood.foodid = 5;
food.foodid = 8;
//totalGroup = 58;
cout << "info()" << endl;
}
int CAnimal::getTotalGroup()
{
//totalGroup = 58;
cout << "getTotalGroup()" << endl;
return totalGroup;
}
void use_const_with_class()
{
{
cout << "-----normal instance object-----" << endl;
CAnimal animal;
animal.init();
animal.info();
animal.getTotalGroup();
}
{
cout << "-----const instance object-----" << endl;
CAnimal const canimal;
canimal.init();
//canimal.info();
canimal.getTotalGroup();
}
}
output:
-----normal instance object-----
CFood(int)
CFood()
CAnimal()
init()
info()
getTotalGroup()
~CAnimal()
~CFood()
~CFood()
-----const instance object-----
CFood(int)
CFood()
CAnimal()
init()
getTotalGroup()
~CAnimal()
~CFood()
~CFood()
总结:
- 构造函数和析构函数不能定义为const函数,因为构造函数和析构函数设计本意就是用来改变对象状态的,定义为const函数与构造函数和析构函数设计本意矛盾
- const non-static非类类型数据成员必须在构造函数显式初始化,即在构造函数初始化列表的初始化式中显式初始化,不能进行默认初始化(omit),本质就是const对象必须初始化(有初值),自此const non-static非类类型数据成员不可修改
- const non-static函数成员的本质是修饰this隐含参数,使this实例对象状态不可修改,因此const non-static函数成员不可修改自身状态(non-static数据成员),static数据成员不属于this成员,因此不受const non-static函数成员的const影响
- static函数成员不能定义为const函数,因为static函数成员无this隐含参数,const不知道修饰谁
- const类型指针不能转非const类型指针,反之,非const类型指针可转const类型指针,即classname const*不能转classname*,但classname*可转classname const*,因此const实例对象只能调用const non-static成员函数,非const实例对象可调用const non-static成员函数和non-const non-static成员函数
- 尽管构造函数和析构函数不能定义为const函数,而const实例对象只能调用const non-static成员函数,但const实例对象可调用构造函数和析构函数,否则const实例对象就无法构造和析构了