Reputation: 47
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
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
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
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