[C++系列] 26. static成员

1. 面试题

有这样一个面试题:实现一个类,计算中程序中创建出了多少个类对象?

class Date {
public:
	explicit Date(int year = 1900)
		:_year(year)
	{}
	Date(const Date& d) {
		_year = d._year;
	}
private:
	int _year;
};

Date fun(Date d) {
	return d;
}

int main() {
	Date d(2019);    // 1 构造
	fun(d);          // 2 3 传值引发拷贝构造,构造出一个局部变量,返回值外部拷贝构造,共生成两个对象
	system("pause");
	return 0;
}

首先,调用函数发生一个拷贝构造出一个新的局部变量在函数栈帧中,该函数调用完之后,返回的不为d对象本身,函数调用完毕栈帧销毁,该局部变量不存在。所以为传值做返回,又引发一次值拷贝,拷贝构造出的新的对象返回到外部函数栈帧中。所以生成了两个对象。

class Date {
public:
	explicit Date(int year = 1900)
		:_year(year)
	{
		cout << "Date(int year)" << endl;
	}
	Date(const Date& d) {
		_year = d._year;
		cout << "Date(cosnt Date& d)" << endl;
	}
	Date& operator=(const Date& d) {
		if (this != &d) {
			_year = d._year;
		}
		cout << "operator=(const Date& d)" << endl;
		return *this;
	}
private:
	int _year;
};


Date fun(Date d) {
	return d;
}

int main() {
	Date d(2019);     // 1 构造
	Date d2(2018);    // 2 构造
	Date d3 = d;      // 3 拷贝构造
	d2 = d;           // 不会创建,赋值运算符重载
	fun(d);           // 4 5 传值拷贝构造 返回值拷贝构造
	system("pause");
	return 0;
}
class A {
public:
    A() {++_scount;}
    A(const A& t) {++_scount;}
    static int GetACount() { return _scount;}
private:
    static int _scount;          // 静态成员
};
 
int Test::_count = 0;
 
void TestA() {
    cout<<A::GetACount()<<endl;
    A a1, a2;
    A a3(a1);
    cout<<A::GetACount()<<endl;
}

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态的成员变量一定要在类外进行初始化。

2. 特性

1)静态成员为所有类对象所共享,不属于某个具体的实例。普通成员属于对象,可以理解为静态成员属于所有对象,属于该类。可以通过类名+作用域限定符直接访问,也可以通过对象. 该方式进行访问。而普通成员无法用类名进行访问,因为普通成员属于对象,无法用类名进行调用访问。因为普通成员属于对象,而采用类名进行调用时无法确定属于哪个对象,导致调用出错。而静态成员全局唯一,为所有类对象共享,不会产生歧义,那么就可以采用类名进行调用。
2)静态成员变量必须在类外定义,定义时不添加static关键字。
3)静态成员函数没有隐藏的this指针,不能访问任何非静态成员。静态成员函数可以用类名进行调用,类名不为对象,无法传一个对象的地址。
4)静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值,const修饰符等参数。

在需要所有对象所公有的一个变量就需要定义一个静态成员。静态成员的大小不算在对象中,因为其不存在对象当中。

3. 静态成员函数

静态成员无法调用非静态成员。

class Date {
public:
	void fun() {
        getC();
	}
	static int getC() {
        // 静态成员函数不能调用非静态成员函数,因为静态成员函数没有this指针
		//fun(this);
		return Count;
	}
private:
	int _year;
	static int Count;
};
int Date::Count = 0;



int main() {
	fun();
	system("pause");
	return 0;
}

 非静态成员函数可以调用静态成员函数。静态成员函数调用时无特殊需求,可以进行调用。而非静态成员函数调用需要传入this指针,所以不能满足其要求而无法调用。

猜你喜欢

转载自blog.csdn.net/yl_puyu/article/details/89065047