使用静态成员函数访问静态数据成员

时间:2017-05-26 09:45:28

标签: c++ class static static-members private-members

我试图使用静态成员函数访问静态数据成员,以便我可以调用此函数并检索数据成员。目标是增加/减少此静态数据成员以计算程序中存在的对象数。

从作业逐字逐句:

  

应该提供一个名为getNumObjects的静态成员函数,该函数不接受任何参数并返回一个int,表示当前存在的Complex类型的对象数。

到目前为止我的代码:

Complex.hpp

class Complex{
public:
...
// Get the number of complex objects in the current program
        static int& getNumObjects();
...

private:
...
        static int counter; // static counter
...
}

Complex.cpp

// Initialize object counter for getNumObjects()
int Complex::counter = 0;
// Get number of objects existing in the current program
static int& Complex::getNumObjects(){
        return counter;
}

testComplex.cpp

// checks to see how many complex objects are open currently
        std::cout << "How many complex objecst are in existence? ";
        int num = Complex::getNumObjects();
        std::cout << num << '\n';
        std::cout << "successful\n";

我不明白为什么编译器不断向我发出这个错误:

 error: cannot declare member function ‘static int& Complex::getNumObjects()’ to have static linkage [-fpermissive]
 static int& Complex::getNumObjects(){

或此错误:

In function ‘int getNumObjects()’:
/../../../ error: ‘counter’ was not declared in this scope
  return counter;
         ^~~~~~~
/../../../ note: suggested alternative: ‘toupper’
  return counter;
         ^~~~~~~
         toupper

我已经进行了广泛的搜索,我似乎已经初始化了我的私有数据成员以及函数。 getNumObjects()被声明为一个类,为什么它说函数的范围不正确?

3 个答案:

答案 0 :(得分:4)

  

我不明白为什么编译器不断给我这个错误:

因为您在成员函数定义中重复了static。该函数已经声明为static; C ++语法要求您省略cpp文件中的static

int Complex::counter = 0;
// Get number of objects existing in the current program
int& Complex::getNumObjects(){
    return counter;
}

注意:返回int&可能不是一个好主意,因为调用者可以在您不知情的情况下修改counter

Complex::getNumObjects() = -123; // <<== returning reference makes this legal

这非常糟糕,因为它完全破坏了封装。从本质上讲,您的counter最终会被公开,就像它是公共成员变量一样。

您应该更改函数以返回int

int Complex::getNumObjects(){
    return counter;
}

答案 1 :(得分:1)

static关键字只应在class声明中使用。方法实现应省略static声明:

int& Complex::getNumObjects(){
        return counter;
}

奇怪的是,您已经遵循此规则作为静态成员变量; - )

答案 2 :(得分:0)

您必须跟踪析构函数和构造函数中的对象。此外,您真的希望您的计数器为atomic,以便在多个线程上运行时不会出现竞争条件。

struct Complex
{
  Complex()
  { ++counter; }

  Complex(Complex const&other)
  : _real(other._real), _imag(other._imag)
  { ++counter; }

  Complex(double r, double i=0)
  : _real(r), _imag(i)
  { ++counter; }

  // and so on for all other constructors

  Complex&operator=(Complex const&) = default;

  Complex&operator=(double x)
  {
    _real = x;
    _imag = 0;
    return *this;
  }

 ~Complex() { --counter; }

  static int getNumObjects() { return counter; }

private:
  double _real,_imag;
  static std::atomic<int> counter;
};

实际上并不需要移动构造函数(因为堆上的数据不是由Complex管理的)。