Reputation: 205
I have a following snippet of code:
class Person {
std::string name_;
std::string surname_;
//static vector<???> tracer_;
public:
Person(std:: string name, std::string surname)
: name_(name)
, surname_(surname) {
//something with tracer_
}
~Person() {
//something with tracer_
}
static void OutputPersons(std::ostream& out) {
//print every element in tracer_
}
};
class Worker {
Person person_;
std::string position_;
public:
Worker(const Person& person, std::string position)
: person_(person)
, position_(position) {
}
};
What I want to achieve, is to print all instances of objects of class Person (name and surname, without position from class Worker) which exists at particular moment, so in example
Person s("aaa", "bbb");
Person t("ccc", "ddd");
{
Person u("eee", "fff");
}
Worker w(Person("ggg","hhh"),"guard");
Person::OutputPersons(std::cout);
should print only
aaa bbb
ccc ddd
ggg hhh
as only these objects exists at the moment of calling Person::OutputPersons.
What I don't know is how to project class Person fields. As you see, I have been trying to make a static vector which should "trace" all objects of Person - with adding an element in constructor and removing in destructor. I only have a problem with type of elements in this vector, as I cannot put there any kind of pointer to class Person object.
EDIT:
As I get known it's legitimate to have a vector of Person*, I modified my code
class Person {
std::string name_;
std::string surname_;
static std::vector<Person *> tracer_;
public:
Person(std:: string name, std::string surname)
: name_(name)
, surname_(surname) {
tracer_.push_back(this);
}
but I'm getting error "undefined reference to 'Person::tracer_'. What am I doing wrong?
Upvotes: 0
Views: 1289
Reputation: 14313
To answer your comment, yes, it is perfectly valid to have pointers to a class a data members in your class.
However, there are a few modifications that you need to make to your code. For instance, in your setup the "ggg hhh" Person is not displayed because it is a temporary object whose destructor is called immediately after it is passed to the function. In order to catch this object, you have to add a user-defined copy-constructor to catch the object created in the function:
#include <iostream>
#include <algorithm>
#include <vector>
class Person
{
private:
std::string name_;
std::string surname_;
static std::vector<Person*> tracer_;
public:
Person(std:: string name, std::string surname)
: name_(name),
surname_(surname)
{
tracer_.push_back(this); //add the person
}
//copy constructor
Person(const Person& p) : name_(p.name_), surname_(p.surname_)
{
tracer_.push_back(this); //add the person
}
~Person()
{
tracer_.erase(std::remove(tracer_.begin(), tracer_.end(), this), tracer_.end()); //remove the person, little messy
}
static void OutputPersons(std::ostream& out)
{
for (std::vector<Person*>::iterator it = tracer_.begin(); it != tracer_.end(); it++) //iterate through vector and print all members
{
out << (*it)->name_ << ' ' << (*it)-> surname_ << '\n';
}
}
};
class Worker
{
private:
Person person_;
std::string position_;
public:
Worker(const Person& person, std::string position)
: person_(person),
position_(position)
{
}
};
To answer your new question, you must define tracer_outside of your class like this:
std::vector<Person*> Person::tracer_;
That's just how static class variables work in C++.
With these modifications, the output is:
aaa bbb
ccc ddd
ggg hhh
Note: it would probably be a better design for Worker
to inherit from Person
rather than maintain a Person
field.
Upvotes: 3