Reputation: 297
The question is pretty simple .Currently i am working on a project which have a class lets call it ResoureceHandler.cpp
. This class has some properties , method which is needed by the remaining classes . some properties like username, userid which i can get , set simply by calling resourceHandler->getUserName()
or vice versa . I can think of two ways
Method 1: Make the class singleton and access the method to get , set.
Method 2 make the class and properties static and access them without any instance .
But i am not sure either of them fall into proper design . What should be the ideal way to solve this kind problem ?
Upvotes: 0
Views: 718
Reputation: 5166
Rather suggesting a 3rd method. Avoid using global variables or singletons. A clean code should be the key. Use helper functions when necessary and namespaces like so. If your class is complex, use a proxy design pattern to reduce complexity of class objects and for a cleaner code.
//foo.h ( Avoid instantiating the foo class yourself)
namespace myproject { namespace part1
{
class foo
{
string username_;
public:
foo() { username_ = "foo";}
//properties
string get_username() const { return username_; }
//methods
};
// helper functions
string get_username();
}
}
// foo.cpp
namespace myproject { namespace part1
{
shared_ptr<foo>& get_foo()
{
static shared_ptr<foo> pt;
if( pt == nullptr)
pt = make_shared<foo>();
return pt;
}
string get_username()
{
return get_foo()->get_username();
}
}
}
//poo.h
namespace myproject { namespace part2
{
class poo
{
string username_;
public:
poo(){ username_ = "poo";}
//properties
string get_username() const {return username_;}
//methods
};
// helper functions
string get_username();
}
}
main.cpp
using namespace myproject;
int main()
{
cout << part1::get_username() << endl;
auto str2 = part2::get_username();
return 0;
}
Upvotes: 1
Reputation: 1799
Well, if you want something high performance. Use either of the two methods.
But if you want good coding practice like other languages. You can try something like this:
class User {
private:
int id;
string name;
public:
User(int id, const string &name): id(id), name(name) {}
inline int getId() const { return id; }
inline const string &getName() const { return name; }
// Make a shared object of the User class
static shared_ptr<User> currentUser;
static inline void logIn(int id, const string &name) {
User::currentUser = std::make_shared<User>(id, name);
}
};
shared_ptr<User> User::currentUser = 0;
void doSomethingLengthyWithUser(shared_ptr<User> user) {
static mutex mut; // The lock, for printing
// Simulate long running process
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
// This (lock block) is only to make the printed output consistent
// Try to remove the block, and use the "cout" line only, and see.
{
lock_guard<mutex> l(mut);
cout << "Done it with: " << user->getName() << endl;
}
}
int main() {
// Login first user
User::logIn(1, "first");
cout << "Logged in: " << User::currentUser->getName() << endl;
// Now, we want to do something lengthy with the current user.
// If you were in a different class, you could use the static variable
std::thread doWithFirst(doSomethingLengthyWithUser, User::currentUser);
// Login the second user
User::logIn(2, "second");
cout << "Logged in: " << User::currentUser->getName() << endl;
// Do the lengthy operation with the second also
std::thread doWithSecond(doSomethingLengthyWithUser, User::currentUser);
// Wait for the second thread to end;
doWithSecond.join();
return 0;
}
Why all this?
If there was a lengthy user-related operation, and you suddenly mutate the currentUser. Being a shared_ptr this makes it still unreleased and unmutated INSIDE THE OPERATION, while the static variable will refer to the new one. Also an alternative approach is using copying, but in C++ it may cause some performance problem.
Upvotes: 1