JaayW
JaayW

Reputation: 47

Using Static Member Function to Access Static Data Member

I am trying to access a static data member using a static member function, so that I may call this function and retrieve the data member. The goal is to increase/decrease this static data member to count how many objects are existing in the program.

Verbatim from assignment:

A static member function called getNumObjects should be provided that takes no parameters and returns an int indicating the number of objects of type Complex currently in existence.

My code so far:

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";

I don't understand why the compiler keeps throwing me this error:

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

or this error:

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

I've searched far and wide, I seem to have initialized my private data member just fine as well as the function. getNumObjects() is stated as a class, so why is it saying the scope of the function isn't right?

Upvotes: 1

Views: 2117

Answers (3)

Walter
Walter

Reputation: 45424

You definitely must keep track of the objects in the destructor and constructor. Also, you really want your counter to a atomic so that no race condition occurs when running on multiple threads.

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;
};

There is not really the need for a move constructor (since no data on the heap are managed by Complex).

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726509

I don't understand why the compiler keeps throwing me this error:

Because you repeated static in the member function definition. The function is already declared static; C++ syntax requires you to omit static in the cpp file:

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

Note: It is probably not a good idea to return int&, because the callers would be able to modify counter without your knowledge:

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

This is very bad, because it completely breaks encapsulation. Essentially, your counter ends up being exposed as if it were a public member variable.

You should change your function to return int instead:

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

Upvotes: 4

keith
keith

Reputation: 5332

The static keyword should be used in the class declaration only. The method implementation should omit the static declaration:

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

Oddly, you have already followed this rule for your static member variable ;-)

Upvotes: 1

Related Questions