静态成员函数访问非静态数据成员
⑴ 静态成员函数怎么引用该类中的非静态成员函数
最佳答案,感觉有些没说明白,是说静态成员函数调用了原类的普通成员函数拷贝构造函数和析构函数么?修改了下代码,大致可以看清:
#include<iostream>
using namespace std;
class Myclass
{
private:
int m; //非静态数据成员
static int n; //静态数据成员
public:
Myclass(); //构造函数
Myclass(Myclass &r); //拷贝构造函数
static int getn(Myclass a); // 静态成员函数
~Myclass(); //析构函数
};
Myclass::Myclass()
{
m = 10;
cout << "调用构造函数" << endl;
}
Myclass::Myclass(Myclass &r)
{
m = r.m;
cout << "调用拷贝构造函数" << endl;
}
Myclass::~Myclass()
{
cout << "调用析构函数" << endl;
}
int Myclass::getn(Myclass a)
{
cout << a.m << endl; // 通过类间接使用 非静态数据成员
return n; // 直接使用 静态数据成员
}
int Myclass::n = 100; // 静态数据成员初始化
void main()
{
Myclass app1;
cout << app1.getn(app1) << endl; // 利用对象引用静态函数成员
cout << Myclass::getn(app1) << endl; // 利用类名引用静态函数成员
system("pause");
}
这里还有个改来的例子,原例子是讲静态成员函数调用静态成员变量的。网址:网页链接
我在这里再构造一个普通成员函数,用静态成员函数调用它,碰到普通成员函数只能通过对象调用的问题,因此在静态成员函数中定义了一个默认值的对象(面积是0.不会计数图形个数),但是每次这个对象销毁后(即这个静态成员函数调用之后)系统会调析构函数,使图形计数减1,所以我在这里强行加1.最终编译运行是可以的,可以参考下。
#include <iostream>
using namespace std;
class CRectangle
{
private:
int w=0, h=0;
static int totalArea; //矩形总面积
static int totalNumber; //矩形总数
public:
CRectangle() {};
CRectangle(int w_, int h_);
CRectangle(CRectangle & r);
~CRectangle();
void PrintCRectangle();
static void PrintTotal();
};
CRectangle::CRectangle(int w_, int h_)
{
w = w_; h = h_;
totalNumber++; //有对象生成则增加总数
totalArea += w * h; //有对象生成则增加总面积
}
CRectangle::CRectangle(CRectangle & r)
{
totalNumber++;
totalArea += r.w * r.h;
w = r.w; h = r.h;
}
CRectangle::~CRectangle()
{
totalNumber--; //有对象消亡则减少总数
totalArea -= w * h; //有对象消亡则减少总而积
}
void CRectangle::PrintCRectangle()
{
cout << this->totalNumber << "," << this->totalArea << endl;
}
void CRectangle::PrintTotal()
{
CRectangle a;
/*cout << totalNumber << "," << totalArea << endl;*/
a.PrintCRectangle();
totalNumber++;
}
//必须在定义类的文件中对静态成员变量进行一次声明 //或初始化,否则编译能通过,链接不能通过
int CRectangle::totalNumber = 0;
int CRectangle::totalArea = 0;
int main()
{
CRectangle r1(1, 1);
CRectangle *r2 = new CRectangle(2, 2);
CRectangle r3(r1);
//cout << CRectangle::totalNumber; //错误,totalNumber 是私有
CRectangle::PrintTotal();
r2->PrintTotal();
r3.PrintTotal();
delete r2;
CRectangle::PrintTotal();
r1.PrintTotal();
r3.PrintTotal();
return 0;
}
再改一个版本,仿照最佳答案,在静态成员函数中参数可以是类的对象,则在函数中不再定义类的对象,直接使用对象调用类的普通成员函数。由于这样做在调用静态成员函数时会对类对象初始化,调用构造函数(调用拷贝构造函数),则会对面积加和,计数会加1,而此函数调用结束,还会调用析构函数,会将面积减小,计数减1,所以会在下面的一些函数中加一些处理。最终结果,和上面是对得上的。
#include <iostream>
using namespace std;
class CRectangle
{
private:
int w=0, h=0;
static int totalArea; //矩形总面积
static int totalNumber; //矩形总数
public:
CRectangle() {};
CRectangle(int w_, int h_);
CRectangle(CRectangle & r);
~CRectangle();
void PrintCRectangle();
static void PrintTotal(CRectangle a);
};
CRectangle::CRectangle(int w_, int h_)
{
w = w_; h = h_;
totalNumber++; //有对象生成则增加总数
totalArea += w * h; //有对象生成则增加总面积
}
CRectangle::CRectangle(CRectangle & r)
{
totalNumber++;
totalArea += r.w * r.h;
w = r.w; h = r.h;
}
CRectangle::~CRectangle()
{
totalNumber--; //有对象消亡则减少总数
totalArea -= w * h; //有对象消亡则减少总而积
}
void CRectangle::PrintCRectangle()
{
cout << this->totalNumber << "," << this->totalArea << endl;
totalArea += this->w * this->h;
totalNumber++;
}
void CRectangle::PrintTotal(CRectangle a)
{
totalArea -= a.w * a.h;
totalNumber--;
/*cout << totalNumber << "," << totalArea << endl;*/
a.PrintCRectangle();
}
//必须在定义类的文件中对静态成员变量进行一次声明 //或初始化,否则编译能通过,链接不能通过
int CRectangle::totalNumber = 0;
int CRectangle::totalArea = 0;
int main()
{
CRectangle r1(1, 1);
CRectangle *r2 = new CRectangle(2, 2);
CRectangle r3(r1);
//cout << CRectangle::totalNumber; //错误,totalNumber 是私有
CRectangle::PrintTotal(r1);
r2->PrintTotal(*r2);
r3.PrintTotal(r3);
delete r2;
CRectangle::PrintTotal(r1);
r1.PrintTotal(r3);
r3.PrintTotal(r3);
return 0;
}
上述代码还可以改成:
void CRectangle::PrintCRectangle()
{
cout << this->totalNumber << "," << this->totalArea << endl;
//totalArea += this->w * this->h;
//totalNumber++;
}
void CRectangle::PrintTotal(CRectangle a)
{
totalArea -= a.w * a.h;
totalNumber--;
/*cout << totalNumber << "," << totalArea << endl;*/
a.PrintCRectangle();
totalArea += a.w * a.h;
totalNumber++;
}
即,只在PrintTotal函数中处理面积和计数的变化。
如果上面程序中将拷贝构造函数去掉,则结果会出错。