Working on a small role-playing game battle system to practice object-oriented code. I have a Party class, which has a vector to store a variable amount of party members.
Initializing my party and adding a member seems to work great. I'm even able to call the member's take_damage() function to change the member's hp and that seems to work too.
But when I check on the same member's hp on the next line using the hp getter, it's right back where it started.
I made a destructor for the member class to see what was going on and according to the output the object is being destroyed many times. Why is this?
class Member
{
private:
int hp;
public:
Member() { hp = 1; }
~Member() { std::cout << "DESTROYED!!" << std::endl; }
int get_hp() { return hp; }
void take_damage(int amt) { hp += amt }
};
class Party {
private:
std::vector<Member> members;
public:
void add_member(Member memb) { members.push_back(memb); }
Member get_member(int num) { return members[num]; }
};
int main() {
Party p;
Member m;
p.add_member(m);
std::cout << p.get_member(0).get_hp() << std::endl;
p.get_member(0).take_damage(4);
std::cout << p.get_member(0).get_hp() << std::endl;
}
Your get_member method returns a copy of the array element, rather than a reference to it. Return a reference, and the member will be modified.
Member& get_member(int num) { return members[num]; }
see small issue in code -=amt
also changed function of get_member
other than that, the code seems fine.
class Member
{
private:
int hp;
public:
Member() { hp = 1; }
~Member() { std::cout << "DESTROYED!!" << std::endl; }
int get_hp() { return hp; }
void take_damage(int amt) { hp -= amt } // This should be -=amt, not +=amt
};
class Party {
private:
std::vector<Member> members;
public:
void add_member(Member memb) { members.push_back(memb); }
Member& get_member(int num) { return members[num]; }
};
int main() {
Party p;
Member m;
p.add_member(m);
std::cout << p.get_member(0).get_hp() << std::endl;
p.get_member(0).take_damage(4);
std::cout << p.get_member(0).get_hp() << std::endl;
}
Related
I see the use of a Singleton pointer with online examples, so when I created my own Singleton without a pointer I became very confused as to why every example uses a pointer.
Why is a pointer better than a reference?
Here's my code:
class SimpleSingleton{
private:
static int integerDataMember;
static SimpleSingleton singletonInstance;
SimpleSingleton(){}
public:
static SimpleSingleton GetInstance(){
return singletonInstance;
}
void IncrementDataMember() const { integerDataMember++; }
int GetDataMember() const { return integerDataMember; }
};
SimpleSingleton SimpleSingleton::singletonInstance;
int SimpleSingleton::integerDataMember = 0;
int main()
{
SimpleSingleton::GetInstance().IncrementDataMember();
cout << SimpleSingleton::GetInstance().GetDataMember() << endl;
{
SimpleSingleton::GetInstance().IncrementDataMember();
cout << SimpleSingleton::GetInstance().GetDataMember() << endl;
}
return 0;
}
Today I'm working on a singleton test case in c++.
The singleton is working fine but I would like to instantiate the static object when the user try to access a member of it, so if the variable isn't created when we try to access a member of it, it will not crash instead it will simply generate my singleton.
Here's my class.h:
class PDG : public EmployeRH
{
public:
static void Instantiate(std::string nom, std::string prenom);
// Current manual instantiation version of the singleton
PDG* operator->();
// This is the line I just added to overload "->" operator ... But it seems it's never called.
void SePresenter();
static PDG* _instance;
private:
PDG();
~PDG();
PDG(std::string nom, std::string prenom);
int _budget;
};
Methods.cpp
PDG* PDG::_instance=NULL;
PDG::PDG()
{
}
PDG::~PDG()
{
}
PDG::PDG(std::string a_nom, std::string a_prenom):EmployeRH(a_nom,a_prenom)
{
_budget = 100000;
}
void PDG::Instantiate(std::string a_nom, std::string a_prenom)
{
cout << "instantiation pdg" << endl;
if (_instance == NULL)
{
_instance = new PDG(a_nom,a_prenom);
}
}
PDG* PDG::operator->()
{
PDG::Instantiate("Unknown", "Unknown");
return _instance;
}
void PDG::SePresenter()
{
cout << _nom << " " << _prenom << endl;
}
main.cpp
void main()
{
PDG::_instance->SePresenter();
system("pause");
}
The thing is, it goes directly into "SePresenter()" and not into my overloaded operator "->".
If anyone could help it would be greatfull.
Thanks,
Impact
PDG::_instance is a pointer to PDG so -> simply dereferences the pointer and you can't override the behaviour. To override the -> operator you must call it on the class directly not on a pointer: (*PDG::_instance)->SePresenter(). To preserve your desired syntax and to remove the undefined behaviour from dereferencing the null pointer you can change PDG::_instance into a structure which holds your instance pointer.
#include <string>
#include <iostream>
using namespace std;
struct EmployeRH {
EmployeRH() {}
EmployeRH(std::string nom, std::string prenom) {}
std::string _nom;
std::string _prenom;
};
class PDG : public EmployeRH {
public:
static PDG* Instantiate(std::string nom, std::string prenom);
// Current manual instantiation version of the singleton
void SePresenter();
static struct Instance {
PDG* operator->()
{
return PDG::Instantiate("Unknown", "Unknown");
}
} _instance;
private:
PDG();
~PDG();
PDG(std::string nom, std::string prenom);
int _budget;
};
PDG::Instance PDG::_instance;
PDG::PDG()
{
}
PDG::~PDG()
{
}
PDG::PDG(std::string a_nom, std::string a_prenom)
: EmployeRH(a_nom, a_prenom)
{
_budget = 100000;
}
PDG* PDG::Instantiate(std::string a_nom, std::string a_prenom)
{
static PDG instance(a_nom, a_prenom);
cout << "instantiation pdg" << endl;
return &instance;
}
void PDG::SePresenter()
{
cout << _nom << " " << _prenom << endl;
}
int main()
{
PDG::_instance->SePresenter();
return 0;
}
I've also changed your singleton to use a function static which makes your code thread safe.
So, I was wondering how to create some kind of a code audit in C++ using a tracking mechanism of sorts.
Consider the following classes, where two separate mirrors, A and B, provide messages to a listener.
class MirrorA
{
void one(int a) { m_mirrrorListener.three(a); }
};
class MirrorB
{
void two(int b) { m_mirrrorListener.three(b); }
};
class MirrorListener
{
void three(int c) { std::cout << c << std::endl; }
};
Now, let's say that, for some reason, three needs to know if it was triggered by one() or two().
We can pass along a value like so:
enum mirrorSource_t
{
FROM_ONE = 1,
FROM_TWO = 2
}
class MirrorA
{
void one(int a) { m_mirrrorListener.three(a, FROM_ONE); }
};
class MirrorB
{
void two(int b) { m_mirrrorListener.three(b, FROM_TWO); }
};
class MirrorListener
{
void three(int c, mirrorSource_t source) { std::cout << c << " From " << source << std::endl; }
};
But then we have to update the signature of three and its invocation whenever it needs new information.
So, what if we had a singleton message tracker (referenced as m_mirrorMessageTracker in other classes) that could track an arbitrary number of messages?
enum mirrorSource_t
{
FROM_ONE = 1,
FROM_TWO = 2
}
class MirrorMessage
{
public:
MirrorMessage(mirrrorSource_t t) : source(t) {}
get() { return source; }
private:
mirrorSource_t source;
};
class MirrorMessageTracker {
public:
MirrorMessage& MirrorMessageTracker::trackEvent(mirrorSource_t value)
{
trackedMessages.push_back(MirrorMessage(value));
return trackedMessages.back();
}
MirrorMessage& MirrorMesssageTracker::getCurrentEvent()
{
return trackedMessages.back();
}
static MirrorMessageTracker& getInstance()
{
if(!m_Tracker)
{
m_pTracker = new MirrorMessageTracker();
}
return *m_pTracker;
}
private:
MirrorMessageTracker() { }; //
static MirrorMessageTracker* m_pTracker;
std::vector<MirrorMessage> trackedMessages; // assumption is that tracked messages are
// single-threaded and unwind in a LIFO manner.
};
class MirrorA
{
void one(int a)
{
MirrorMessage createdMessage = m_MirrorMessageTracker.trackMessage(FROM_ONE);
m_mirrrorListener.three(a);
}
};
class MirrorB
{
void two(int b)
{
MirrorMessage createdMessage = m_MirrorMessageTracker.trackMessage(FROM_TWO);
m_mirrrorListener.three(b);
}
};
class MirrorListener
{
void three(int c)
{
MirrorMessage& message = m_MirrorMessageTracker.getCurrentMessage();
if (message.get() == FROM_ONE)
{
std::cout << c << std::endl;
}
else if (message.get() == FROM_TWO)
{
std::cout << c << c << std::endl;
}
else
{
std::cout << c << c << c << std::endl;
}
}
};
I would like for the tracked message to be removed from the tracker after createdMessage goes out of scope in one and two. Can this be done with a particular type of boost smart pointer? Something like:
std::vector<boost::shared_ptr<MirrorMessage> > trackedMessages;
vector::push_back would create a copy of the message and place it into the vector so I'm not sure if it's possible with a shared pointer, though.
The more common pattern to create singletons actually is
static MirrorMessageTracker& getInstance() {
static MirrorMessageTracker theMirrorMesageTracker;
return theMirrorMesageTracker;
}
Also you should consider to forbid copying and assignment for your MirrorMessageTracker class, by making these operations private:
private:
MirrorMessageTracker() { };
MirrorMessageTracker(const MirrorMessageTracker&); // <<<
MirrorMessageTracker& operator=(const MirrorMessageTracker&); // <<<
At the moment I'm dealing with a delightful legacy code class implementing polymorphism by switch-case:
class LegacyClass {
public:
enum InitType {TYPE_A, TYPE_B};
void init(InitType type) {m_type=type;}
int foo() {
if (m_type==TYPE_A)
{
/* ...A-specific work... */
return 1;
}
// else, TYPE_B:
/* ...B-specific work... */
return 2;
}
/** Lots more functions like this **/
private:
InitType m_type;
};
I'd like to refactor this to proper polymorphism, e.g.:
class RefactoredClass {
public:
virtual ~RefactoredClass(){}
virtual int foo()=0;
};
class Class_ImplA : public RefactoredClass {
public:
virtual ~Class_ImplA(){}
int foo() {
/* ...A-specific work... */
return 1;
}
};
class Class_ImplB : public RefactoredClass {
public:
virtual ~Class_ImplB(){}
int foo() {
/* ...B-specific work... */
return 2;
}
};
Unfortunately, I have one crucial problem: due to optimization and architectural considerations, within a primary use of LegacyClass, I cannot use dynamic allocation; the instance is a member of a different class by composition:
class BigImportantClass{
/* ... */
private:
LegacyClass m_legacy;
}
(In this example, BigImportantClass may be dynamically allocated, but the allocation needs to be in one continuous virtual segment, and a single new() call; I can't make further calls to new() in the BigImportantClass ctor or in subsequent initialization methods.)
Is there a good way to initialize a concrete implementation, polymorphically, without using new()?
My own progress so far: What I can do is provide a char[] buffer as a member of BigImportantClass, and somehow initialize a concrete member of RefactoredClass in that memory. The buffer would be large enough to accommodate all implementations of RefactoredClass. However, I do not know how to do this safely. I know the placement-new syntax, but I'm new to dealing with alignment (hence, warned off by the C++-FAQ...), and aligning generically for all concrete implementations of the RefactoredClass interface sounds daunting. Is this the way to go? Or do I have any other options?
Here's some code... just doing the obvious things. I don't use C++11's new union features, which might actually be a more structured way to ensure appropriate alignment and size and clean up the code.
#include <iostream>
template <size_t A, size_t B>
struct max
{
static const size_t value = A > B ? A : B;
};
class X
{
public:
X(char x) { construct(x); }
X(const X& rhs)
{ rhs.interface().copy_construct_at_address(this); }
~X() { interface().~Interface(); }
X& operator=(const X& rhs)
{
// warning - not exception safe
interface().~Interface();
rhs.interface().copy_construct_at_address(this);
return *this;
}
struct Interface
{
virtual ~Interface() { }
virtual void f(int) = 0;
virtual void copy_construct_at_address(void*) const = 0;
};
Interface& interface()
{ return reinterpret_cast<Interface&>(data_); }
const Interface& interface() const
{ return reinterpret_cast<const Interface&>(data_); }
// for convenience use of virtual members...
void f(int x) { interface().f(x); }
private:
void construct(char x)
{
if (x == 'A') new (data_) Impl_A();
else if (x == 'B') new (data_) Impl_B();
}
struct Impl_A : Interface
{
Impl_A() : n_(10) { std::cout << "Impl_A(this " << this << ")\n"; }
~Impl_A() { std::cout << "~Impl_A(this " << this << ")\n"; }
void f(int x)
{ std::cout << "Impl_A::f(x " << x << ") n_ " << n_;
n_ += x / 3;
std::cout << " -> " << n_ << '\n'; }
void copy_construct_at_address(void* p) const { new (p) Impl_A(*this); }
int n_;
};
struct Impl_B : Interface
{
Impl_B() : n_(20) { std::cout << "Impl_B(this " << this << ")\n"; }
~Impl_B() { std::cout << "~Impl_B(this " << this << ")\n"; }
void f(int x)
{ std::cout << "Impl_B::f(x " << x << ") n_ " << n_;
n_ += x / 3.0;
std::cout << " -> " << n_ << '\n'; }
void copy_construct_at_address(void* p) const { new (p) Impl_B(*this); }
double n_;
};
union
{
double align_;
char data_[max<sizeof Impl_A, sizeof Impl_B>::value];
};
};
int main()
{
{
X a('A');
a.f(5);
X b('B');
b.f(5);
X x2(b);
x2.f(6);
x2 = a;
x2.f(7);
}
}
Output (with my comments):
Impl_A(this 0018FF24)
Impl_A::f(x 5) n_ 10 -> 11
Impl_B(this 0018FF04)
Impl_B::f(x 5) n_ 20 -> 21.6667
Impl_B::f(x 6) n_ 21.6667 -> 23.6667
~Impl_B(this 0018FF14) // x2 = a morphs type
Impl_A::f(x 7) n_ 11 -> 13 // x2 value 11 copied per a's above
~Impl_A(this 0018FF14)
~Impl_B(this 0018FF04)
~Impl_A(this 0018FF24)
I implemented this using C++11 unions. This code seems to work under g++ 4.8.2, but it requires the -std=gnu++11 or -std=c++11 flags.
#include <iostream>
class RefactoredClass {
public:
virtual ~RefactoredClass() { }; // Linking error if this is pure. Why?
virtual int foo() = 0;
};
class RefactorA : RefactoredClass {
double data1, data2, data3, data4;
public:
int foo() { return 1; }
~RefactorA() { std::cout << "Destroying RefactorA" << std::endl; }
};
class RefactorB : RefactoredClass {
int data;
public:
int foo () { return 2; }
~RefactorB() { std::cout << "Destroying RefactorB" << std::endl; }
};
// You may need to manually create copy, move, &ct operators for this.
// Requires C++11
union LegacyClass {
RefactorA refA;
RefactorB refB;
LegacyClass(char type) {
switch (type) {
case 'A':
new(this) RefactorA;
break;
case 'B':
new(this) RefactorB;
break;
default:
// Rut-row
break;
}
}
RefactoredClass * AsRefactoredClass() { return (RefactoredClass *)this; }
int foo() { return AsRefactoredClass()->foo(); }
~LegacyClass() { AsRefactoredClass()->~RefactoredClass(); }
};
int main (void) {
LegacyClass A('A');
LegacyClass B('B');
std::cout << A.foo() << std::endl;
std::cout << B.foo() << std::endl;
return 0;
}
Somebody should have made an answer by now...so here's mine.
I'd recommend using a union of char array and one of the biggest integer types:
union {
char refactored_class_buffer[ sizeof RefactoredClass ];
long long refactored_class_buffer_aligner;
};
I also strongly recommend putting an assert or even an if(check) throw; into your factory so that you never, ever, exceed the size of your buffer.
If the data is the same for each case, and you're only changing behaviuor, you don't need to allocate in your core - this is basically a strategy pattern using singleton strategies. You end up using polymorphism in your logic, but not in your data.
class FooStrategy() {
virtual int foo(RefactoredClass& v)=0;
}
class RefactoredClass {
int foo() {
return this.fooStrategy(*this);
}
FooStrategy * fooStrategy;
};
class FooStrategyA : public FooStrategy {
//Use whichever singleton pattern you're happy with.
static FooStrategyA* instance() {
static FooStrategyA fooStrategy;
return &fooStrategy;
}
int foo(RefactoredClass& v) {
//Do something with v's data
}
}
//Same for FooStrategyB
Then when you create a RefactoredClass you set its fooStrategy to FooStrategyA::instance().
It's hard to explain exactly what I want to do here, but I have a base class and two classes which inherit this base class. Both classes which inherit it have their own unique members. I want to be able to pass both to a method, and have that method detect which it is, then access their unique members. I can't assume there will only be two classes which inherit it, so i'm looking for something of a more general solution.
Here is an example of what I'd like to do:
#include <iostream>
class Base {
public:
int _type;
Base() { }
};
class First : public Base {
public:
int _first_only;
First() { }
};
class Second : public Base {
public:
int _second_only;
Second() { }
};
void test (Base b) {
std::cout << "Type: " << b._type << std::endl;
if(b._type==1) {
std::cout << "First\n";
// Want to be able to do this
std::cout << "Val: " << (First)b._first_only << std::endl;
} else if(b._type==2) {
std::cout << "Second\n";
// And this
std::cout << "Val: " << (Second)b._second_only << std::endl;
}
}
int main() {
First f;
f._first_only=1;
f._type=1;
Second s;
s._type=2;
s._second_only=2;
test(f);
test(s);
}
This is similar to others answers:
You can write polymorphic classes to get this behavior using virtual functions.
Pass the Dervied class objects either by pointer or by reference to get polymorphic behaviour. Otherwise it will lead to object slicing. Your test() function leads to object slicing.
This code may also help you. You can see that there are different ways to print the type. I used GetBaseType(), GetDerivedType() and GetType(). Among these GetType() method is convenient for you case. There are two constructors for convenience. Constructors allow to initialize data members.
class Base {
private:
int _type;
public:
Base(int type) : _type(type) { }
int GetBaseType() { return _type; }
virtual int GetDerivedType() = 0;
virtual int GetType() { return _type; }
};
class First : public Base {
private:
int _first_only;
public:
First() : Base(1), _first_only(1) { }
First(int first_only) : Base(first_only), _first_only(first_only) { }
int GetDerivedType() { return _first_only; }
virtual int GetType() { return _first_only; }
};
class Second : public Base {
private:
int _second_only;
public:
Second() : Base(2), _second_only(2) { }
Second(int second_only) : Base(second_only), _second_only(second_only) { }
int GetDerivedType() { return _second_only; }
virtual int GetType() { return _second_only; }
};
void test (Base &b) {
std::cout << "Type: " << b.GetBaseType() << std::endl;
std::cout << "Type: " << b.Base::GetType() << std::endl;
std::cout << "Dervied type: \n";
std::cout << "Val: " << b.GetDerivedType() << std::endl;
std::cout << "Val: " << b.GetType() << std::endl;
}
int main() {
First f(1);
Second s(2);
test(f);
test(s);
First f1;
Second s1;
test(f1);
test(s1);
}
Either declare a virtual function in Base
Move the common members types from First and Second into Base.
For your specific problem, 2nd option is better:
class Base {
public:
int _member; // have getter() method, if '_member' is private
Base() { }
};
Inside, test():
void test (Base &b) { // <--- practice to pass by reference if copy is not needed
// use b._member;
};
Your code does not work polymorphically, because you are passing the function-parameter by value, which results in slicing.
If you have a method that does different things for different types, consider overloading it for each of these types.
Three things I'd do:
In general switching on type codes is not considered good object oriented design: Instead pull the switched code into the classes.
I'd also set up the type tags in the constructor of the specific classes.
And as others have mentioned you need to pass the argument by reference to avoid slicing.
Here's what the code would look like:
#include <iostream>
class Base {
public:
int _type;
Base() { }
virtual void print_to_stream( std::ostream & os ) const =0;
};
class First : public Base {
public:
int _first_only;
First() { _type =1; }
void print_to_stream( std::ostream & os ) const
{
os<<"First\n";
os<<"Val: " << _first_only << std::endl;
}
};
class Second : public Base {
public:
int _second_only;
Second() { _type=2; }
void print_to_stream( std::ostream & os ) const
{
os << "Second\n";
os << "Val: " << _second_only << std::endl;
}
};
void test (Base & b)
{
std::cout << "Type: " << b._type << std::endl;
b.print_to_stream( std::cout );
}
int main() {
First f;
f._first_only=1;
Second s;
s._second_only=2;
test(f);
test(s);
}