C语言中的静态属性
int fun(int a)
{
static int x = a;
int y = 10;
return x;
}
静态关键字修饰局部变量, x 的可见性仍然在此函数中,生存区等改为.data区
,且函数调用仅对x初始化一次
int& fun(int a)
{
static int x = a;
int y = 10;
return x;
}
可以通过引用将局部变量x,进行返回,因为x的生存期已经超出了函数的生存期
static int max = 10; //.data
static int& fun(int a) //.text
{
static int x = a; //.data
int y = 10;
return x;
}
若我们将函数定义为静态,或将全局变量定义为静态
对于全局变量定义为静态,其生存期不变(仍然在.data区
),但是可见性改变,仅能在定义它的文件中可见;而函数定义为静态,同样依旧在.text区
,但是可见性改变,仅能在定义它的文件中可见,同一工程中的其他文件不可见
C++中的静态成员
class Object
{
public:
int value;
static int num;
Object(int x = 0) :value(x)
{
num += 1;
}
Object(const Object& obj) :value(obj.value)
{
num += 1;
}
~Object()
{
num -= 1;
}
};
首先类内的静态成员,无法通过构造函数与拷贝构造函数通过列表方式进行构建,需要通过类外进行初始化类内静态成员
int main()
{
Object obja(10);
Object objb(20);
cout << &obja.value << " " << &obja.num << endl;
cout << &objb.value << " " << &objb.num << endl;
}
可以看到 num 属于所有对象共享的一个成员,静态成员仅有一份,而非静态成员每一个对象都有一份
int main()
{
Object obja(10);
Object objb(20);
cout << &obja.value << " " << &obja.num << endl;
cout << &objb.value << " " << &objb.num << endl;
obja.num += 10;
Object::num = 100;
cout<< Object::num << endl;
}
若静态成员是公有成员,则可以通过类型名进行直接访问
但是更多情况会将静态成员设置为私有,无法在类外进行直接访问,但是类外初始化依旧是正确的;int Object::num = 0;
编译器会在编译连接过程,完成这一部分
class Object
{
private:
int value;
static int num;
public:
void Print() const
{
num += 10;
cout << "value" << this->value << "num" << num << endl;
}
};
在Print函数中,对num进行修改是正确的;这是因为const修饰的是this指针,而静态成员属于所有成员,this指针没有去指向静态成员
class Object
{
private:
int value;
static int num;
public:
void Print() const
{
num += 10;
cout << "value" << this->value << "num" << num << endl;
}
static int Show() //此处静态关键字修饰的是函数本身,而不是返回值
{
num += 10;
cout << "value" << this->value << "num" << num << endl; // 无法访问非静态成员 this->value err!!
}
};
静态函数中,没有this指针,所以它只能访问静态成员,不可以访问非静态成员
int main()
{
Object obja(10);
obja.Print();
//Print(&obja);
obja.Show();
//Show() 没有this指针,所以无法确定value的来源
Object::Show();
//同样可以通过上面的方法去进行访问
}
接下来看下面四个例子
// A
class Object
{
public:
int value;
Object obj;
};
// B
class Object
{
public:
int value;
Object &obj;
};
// C
class Object
{
public:
int value;
Object *pobj
};
// D
class Object
{
public:
int value;
static Object obj;
};
上面四个例子,后两个是正确的,而第一个会引起死递归,第二个引用必须需要引用一个存在的对象
下面的例子中,静态函数只能调用静态成员;静态成员没有this指针,无法访问非静态数据
class Object
{
int value;
static int num;
public:
Object(int x = 0) :value(x) {}
static void Show()//静态函数只能访问静态成员,不能访问非静态成员
{
cout << num << endl;
}
};
int Object::num = 10;
int main()
{
Object obja(10);
Object objb(20);
return 0;
}
若我们希望静态函数也能调用普通成员,将对象作为参数传入函数,来进行访问该对象的非静态数据
class Object
{
int value;
static int num;
public:
Object(int x = 0) :value(x) {}
static void Show(Object& obj)
{
obj.value += 10;
cout << obj.value <<endl;
cout << num << endl;
}
};
int Object::num = 10;
int main()
{
Object obja(10);
Object objb(20);
obja.Show(obja);//将对象作为参数传入进静态函数
obja.Show(objb);
Object::Show(objb);
return 0;
}