I have a lot of free time ( there are also the Xmas holidays incoming! ) so, I tried to merge my two passions, video games and c++.
It is not a real video game project, was just some console script using classes.
So, here it comes the problem;
#include <stdafx.h>
#include <iostream>
class m4a1 {
public:
int Damage = 12;
int Mag = 30;
};
class ak47 {
public:
int Damage = 14;
int Mag = 24;
};
union Gun_Union {
m4a1 M4A1_Union;
ak47 Ak47_Union;
};
class Player {
public:
Gun_Union Gun_Player;
int Health = 200;
};
template <typename Type>
void Shot(Type* Player_Obj) {
Player_Obj->Gun_Player->AK47_Union->Mag--;
Player_Obj->Health = Player_Obj->Health - Player_Obj->Gun_Player->AK47_Union->Damage;
}
int main() {
Player Player_Obj;
Player_Obj.Gun_Player;
Shot <Player> (&Player_Obj);
std::cout << Player_Obj.Health;
}
At the line 35 it gives me the error
Player::Player(void) trying to refer to an eliminate function.
I discovered that changing Gun_Union with any other type in the class Player (line 25) it doesn't give me an error.
I also ask if the command Player_Obj.Gun_Player = Ak47_Union is possible;
Sorry for bad English.
To answer your original question, your union has non-trivial members (because of the initializers), but has no constructor. You need to tell the compiler which of the union's members you want to have initially, because the compiler must construct one or the other. That can be done for example by giving the union a constructor.
And then you're mixing . and -> operators.
Here's a version that compiles (I don't dare call it "fixed" though):
#include <iostream>
class m4a1 {
public:
int Damage = 12;
int Mag = 30;
};
class ak47 {
public:
int Damage = 14;
int Mag = 24;
};
union Gun_Union {
m4a1 M4A1_Union;
ak47 Ak47_Union;
Gun_Union() : Ak47_Union() {} // <=== the initial state is ak47
};
class Player {
public:
union Gun_Union Gun_Player;
int Health = 200;
};
template <typename Type>
void Shot(Type* Player_Obj) {
Player_Obj->Gun_Player.Ak47_Union.Mag--;
Player_Obj->Health = Player_Obj->Health - Player_Obj->Gun_Player.Ak47_Union.Damage;
}
int main() {
Player Player_Obj;
Player_Obj.Gun_Player;
Shot <Player>(&Player_Obj);
std::cout << Player_Obj.Health;
}
I also ask if the command Player_Obj.Gun_Player = Ak47_Union is possible; Sorry for bad English.
So what you're trying to do here is set the player's current weapon to an ak47. Here's the problem. Your union represents a class, not just a regular type. This is a problem for a few reasons.
A class is useful because it provides a blueprint from which to create similar but ultimately different objects. Since all of your weapon classes have the same structure (damage and magsize), there's no reason to have separate classes for each weapon.
Furthermore, a class here is tricky because in order for you to use a class, you must first either instantiate it or declare it's member functions static. The problem here comes from the fact that you're using a union to handle the player weapon. A union won't work because unions by definition hold things (one at a time), which is not a thing here because we want a static class.
Now, you could instantiate your weapon classes and actually add them to the union, like so:
int main()
{
Player Player_Obj;
Player_Obj.Gun_Player;
// Remember to pick better names for classes, not the metasynctactic
// b.s. I'm using
m4a1 m4a1_class_instance;
ak47 ak47_class_instance;
// Populate the union
union Gun_Union weapons;
weapons.Ak47_Union = ak47_class_instance;
// Finally, set player weapon
Player_Obj.Gun_player = weapons;
// <Rest of program...>
As I'm sure you can tell, this is clunky and doesn't really make sense. Why are we istantiating those classes? It doesn't really make sense. I think a redesign here would be great, especially because you wouldn't have to deal with the union, which was tripping you up with regards to setting the player's weapon. Here is a pretty basic one.
// Using constants for simplicity
// Weapon Ids
const auto M4A1 = 1000;
const auto AK47 = 1001;
const auto FIRST_WEAPON_ID = M4A1;
const auto LAST_WEAPON_ID = AK47;
class Player {
int weapon_id;
int health;
int damage;
int magazine_capacity;
int magazine;
public:
void setWeapon(const int weapon_id) {
// Validate id first; you should somehow handle error,
// I'm just exiting the function here
if ((weapon_id < FIRST_WEAPON_ID) || (weapon_id > LAST_WEAPON_ID)) return;
switch (weapon_id) {
case M4A1: {
damage = 12;
magazine_capacity = 30;
} break;
case AK47: {
damage = 14;
magazine_capacity = 24;
} break;
default: // Error should have been handled in validation, but
// it's best practice to guard your code everywhere
return;
}
}
};
This wouldn't be the full class obviously, I only wrote one function just to show you how I would implement a more naive method, but the actually implementation details are up to you, I would really stress the design concepts, specifically the following:
Accessing Class Members
You don't want to access class members directly, especially when you're talking about a pointer. The problem of 'who owns the data pointed to by the pointer' is a significant one, and it's why we now have shared and unique pointers. Regardless of which pointer you use though, you should have something like <return-type> getValue() const. That way your data is protected by a layer of indirection. Likewise, to set a value you can do something like void setValue(const <type> value) and now you can do validation or whatever in that function.
Unions
First, I don't recommend using unions. In your particular case, using a union doesn't really make sense because you already have the pointer in the player class (before you edited your question), which means a player can already only hold one. Having a union doesn't add anything at that point. Additionally, using unions isn't recommended, mostly because you lose some type-safety. If you do want something union-like, you might want to check out std::variant in the STL.
Your Template Function
Generally speaking, template functions are for generic programming, where they can take in a type T and you don't have to worry about rewriting code unnecessarily. In your case, it shouldn't apply.
You mentioned you were just doing this for practice, so I understand a clean design wasn't your goal, but I think it's never too early to start thinking about design principles.
Related
I am trying to optimize the run time of my code and I was told that removing unnecessary virtual functions was the way to go. With that in mind I would still like to use inheritance to avoid unnecessary code bloat. I thought that if I simply redefined the functions I wanted and initialized different variable values I could get by with just downcasting to my derived class whenever I needed derived class specific behavior.
So I need a variable that identifies the type of class that I am dealing with so I can use a switch statement to downcast properly. I am using the following code to test this approach:
Classes.h
#pragma once
class A {
public:
int type;
static const int GetType() { return 0; }
A() : type(0) {}
};
class B : public A {
public:
int type;
static const int GetType() { return 1; }
B() : {type = 1}
};
Main.cpp
#include "Classes.h"
#include <iostream>
using std::cout;
using std::endl;
using std::getchar;
int main() {
A *a = new B();
cout << a->GetType() << endl;
cout << a->type;
getchar();
return 0;
}
I get the output expected: 0 1
Question 1: Is there a better way to store type so that I do not need to waste memory for each instance of the object created (like the static keyword would allow)?
Question 2: Would it be more effective to put the switch statement in the function to decide that it should do based on the type value, or switch statement -> downcast then use a derived class specific function.
Question 3: Is there a better way to handle this that I am entirely overlooking that does not use virtual functions? For Example, should I just create an entirely new class that has many of the same variables
Question 1: Is there a better way to store type so that I do not need to waste memory for each instance of the object created (like the static keyword would allow)?
There's the typeid() already enabled with RTTI, there's no need you implement that yourself in an error prone and unreliable way.
Question 2: Would it be more effective to put the switch statement in the function to decide that it should do based on the type value, or switch statement -> downcast then use a derived class specific function.
Certainly no! That's a heavy indicator of bad (sic!) class inheritance hierarchy design.
Question 3: Is there a better way to handle this that I am entirely overlooking that does not use virtual functions? For Example, should I just create an entirely new class that has many of the same variables
The typical way to realize polymorphism without usage of virtual functions is the CRTP (aka Static Polymorphism).
That's a widely used technique to avoid the overhead of virtual function tables when you don't really need them, and just want to adapt your specific needs (e.g. with small targets, where low memory overhead is crucial).
Given your example1, that would be something like this:
template<class Derived>
class A {
protected:
int InternalGetType() { return 0; }
public:
int GetType() { static_cast<Derived*>(this)->InternalGetType(); }
};
class B : public A<B> {
friend class A<B>;
protected:
int InternalGetType() { return 1; }
};
All binding will be done at compile time, and there's zero runtime overhead.
Also binding is safely guaranteed using the static_cast, that will throw compiler errors, if B doesn't actually inherits A<B>.
Note (almost disclaimer):
Don't use that pattern as a golden hammer! It has it's drawbacks also:
It's harder to provide abstract interfaces, and without prior type trait checks or concepts, you'll confuse your clients with hard to read compiler error messages at template instantiantion.
That's not applicable for plugin like architecture models, where you really want to have late binding, and modules loaded at runtime.
If you don't have really heavy restrictions regarding executable's code size and performance, it's not worth doing the extra work necessary. For most systems you can simply neglect the dispatch overhead done with virtual function defintions.
1)The semantics of GetType() isn't necessarily the best one, but well ...
Go ahead and use virtual functions, but make sure each of those functions is doing enough work that the overhead of an indirect call is insignificant. That shouldn't be very hard to do, a virtual call is pretty fast - it wouldn't be part of C++ if it wasn't.
Doing your own pointer casting is likely to be even slower, unless you can use that pointer a significant number of times.
To make this a little more concrete, here's some code:
class A {
public:
int type;
int buffer[1000000];
A() : type(0) {}
virtual void VirtualIncrease(int n) { buffer[n] += 1; }
void NonVirtualIncrease(int n) { buffer[n] += 1; }
virtual void IncreaseAll() { for i=0; i<1000000; ++i) buffer[i] += 1; }
};
class B : public A {
public:
B() : {type = 1}
virtual void VirtualIncrease(int n) { buffer[n] += 2; }
void NonVirtualIncrease(int n) { buffer[n] += 2; }
virtual void IncreaseAll() { for i=0; i<1000000; ++i) buffer[i] += 2; }
};
int main() {
A *a = new B();
// easy way with virtual
for (int i = 0; i < 1000000; ++i)
a->VirtualIncrease(i);
// hard way with switch
for (int i = 0; i < 1000000; ++i) {
switch(a->type) {
case 0:
a->NonVirtualIncrease(i);
break;
case 1:
static_cast<B*>(a)->NonVirtualIncrease(i);
break;
}
}
// fast way
a->IncreaseAll();
getchar();
return 0;
}
The code that switches using a type code is not only much harder to read, it's probably slower as well. Doing more work inside a virtual function ends up being both cleanest and fastest.
The following is directly related to this. What I would like is to be able to call and have active only one class at a time, to save memory, but also because I plan to add, later on, a GUI, so I'd be able to call the classes through a drop-down menu (for example).
I tried making composition, and this is what came out:
#include <iostream>
class Power
{
private:
double m_x;
public:
Power() {std::cout<<"Power\n";}
Power(double x): m_x {x} {std::cout<<"Power("<<x<<")\n";}
~Power() {std::cout<<"~Power\n";}
const double getX() const { return m_x; }
};
class Scanner
{
private:
Power m_power;
public:
Scanner() {std::cout<<"Scanner\n";}
Scanner(const Power &p): m_power {p} {std::cout<<"Scanner("<<&p<<")\n";}
void print() {std::cout<<"x="<<m_power.getX()<<'\n';}
};
class Printer
{
private:
Power m_power;
public:
Printer() {std::cout<<"Printer\n";}
Printer(const Power &p): m_power {p} {std::cout<<"Printer("<<&p<<")\n";}
void print() {std::cout<<"x="<<m_power.getX()<<'\n';}
};
class Copier // if Copier is to be used for "unification", will "public" be needed?
{
private:
Scanner *m_s;
Printer *m_p;
int m_i;
public:
Copier() {std::cout<<"Copier\n";}
Copier(const Power &p, int i): m_i {i}
{
if (i)
m_s = new Scanner(p);
else
m_p = new Printer(p);
std::cout<<"Copier("<<&p<<","<<i<<")\n";
}
void print() { std::cout << (m_i ? m_s->getX() : m_p->getX()) << '\n'; }
};
int main(int argc, char *argv[])
{
Scanner *s {new Scanner(Power(2.3))};
s->print();
Printer *p {new Printer(Power(3.14))};
p->print();
s->print(); // here, both *s and *p exist, both use memory
// this comes after considering adding class Copier
Copier *c {new Copier(Power(1.618), 0)};
c->print();
c = new Copier(Power(2.718), 1);
c->print();
return 0;
}
Ignore Copier for a bit. As it is, I can use it, and this is what comes out:
Power(2.3)
Scanner(0x7ffc80d98c10)
~Power
x=2.3
Power(3.14)
Printer(0x7ffc80d98c20)
~Power
x=3.14
x=2.3
The (major) problem now is that there are multiple objects in memory, there's *s and there's *p, as you can see x can pe printed out with both 3.14 and 2.3. If I have more than 2 classes (which I do), I could call each class and each will take up memory. That's not something I want.
How can I call only one class at a time and not have to call extra resets or deletes? I thought of adding another class for it, see Copier. But I can't use std::unique_ptr and the solution in the code is, not only extremely ugly, but doesn't even work. Plus it calls constructors like crazy.
I tried using std::unique_ptr in a simple function, with std::make_unique (that needs c++14, and I'd rather keep some larger safety margin, but I could also live with it, too). It also doesn't work because it points to Power (if I call z->print() it says 'class Power' has no member 'print'):
std::unique_ptr<Power> call(const Power &p, const int &i)
{
if (i)
return std::make_unique<Printer>(p);
else
return std::make_unique<Scanner>(p);
}
I don't know how to make this. In short, classes Scanner, Printer, and any other that exist, are dedicated classes that perfom one task, only, unique in their way of computing, and all of them make use of some common variables in Power (besides their own). I don't think it would be very effective to move the common variables to each class because they would only bloat the code, and, as I understand it, "if you can use a storage class instead of repeating the same variable over and over, use it" (not my words, is this true?). Then, I'd like to be able to instantiate those classes, but only have one active at a time, to spare memory.
As an example, suppose one class makes an array of 1mil values, then another makes 1mil different values, and so on. Imagine having that array in memory as many times as there are instantiated classes. I don't want that. The purpose of Copier would have been to call (based on the conditional) only one class at a time. Job done? Call another, but forget anything else that was done before, start anew. And all this to be able to call through only one widget, such as select from list, click&go, that will be added later.
That was a stupid mistake, I forgot to delete public ... after copy-pasting. I also tried the code now (with Copier), it compiles, but still doesn't work, m_x stays empty, even with the very ugly solution of having two Scanner and Printer pointers as member variables inside Copier.
Well, after some tries, I couldn't make what I wanted so I thought to go back to my original idea, even if it meant inheritance. So I came up with this piece of code, where I changed the names to make a bit more sense(?):
#include <iostream>
class Garage
{
protected:
double m_x; // gas, tires, etc, that all cars use, reside in the Garage
public:
Garage() {std::cout<<"Garage\n";}
virtual ~Garage() {std::cout<<"~Garage\n";}
};
class Audi: virtual public Garage
{
public:
Audi() {std::cout<<"Audi\n";}
void f(const double &x) { m_x=x; std::cout<<"Audi::f("<<x<<")\n";}
};
class Bmw: virtual public Garage
{
public:
Bmw() {std::cout<<"Bmw\n";}
void f(const double &x) { m_x=x; std::cout<<"Bmw::f("<<x<<")\n";}
};
class Driver: public Audi, public Bmw
{
private:
double m_y; // report of driving, based on m_x
public:
Driver() {std::cout<<"Driver\n";}
Driver(const double &x, int i)
{
if (i)
Bmw::f(x);
else
Audi::f(x);
m_y = -m_x;
std::cout<<"Driver("<<x<<","<<i<<")\n";
}
void print() { std::cout << "x=" << m_x << ", y=" << m_y << '\n'; }
};
int main(int argc, char *argv[])
{
Driver *d {new Driver(1.618, 0)};
d->print();
d = new Driver(0.618, 1);
d->print();
// even iteration works now
delete d;
d = nullptr; // to be sure it's dead(?)
for (int i=0; i<2; ++i)
{
d = new Driver(3.14, i);
d->print();
}
return 0;
}
Now, this works, but I have a feeling I set a new record on bad code example. Please don't bash me for this, rather point out all the mistakes, or how you would do it to achieve the same result. Still, even if it seems to work as I want, it still calls all the constructors, on all branches, instead of only on the needed ones. I realize (my apologies) I forgot to say that Driver, here, is also responsible for using m_x further, for its m_y (that's why the code is a bit different).
I'd like to point out that I am not fixed in keeping this code, or any other, I am willing to change and adapt, as long as I reach my purpose. But since I am a beginner, I can't make too many combinations, so I am left with presenting whichever result it is that I reached to try and make myself understood. The program above, as it is, when run, gives what I want, even has the possibility of making a loop, which will let me use it much easier in a GUI, later on. The names, as they are, make the most sense in composition, Garage has-a Bmw, and that was what I tried, but I couldn't obtain what I wanted. So, even if this uses inheritance and does not make sense that an Audi is-a Garage, I kept the names to suggest my initial tryout with composition. My main reason for posting this is to show what I would like the program to do. What happens in main() will be used in a GUI, I am thinking of Qt, because I'd like this to run on all 3 major OSes. So having the possibility of calling one car at a time, using it, and also being able to store previous information without having stale objects in memory, only m_x*nr_of_cars, will make it much easier to work with.
Here is one way to do it.
{ // scope begins
Printer p; // note, no pointers
p.print();
} // scope ends, p is gone
Here we have an object that appears, does one thing once, and disappears.
Here is another
boost::variant<Printer,Scaner,Copier> psc(Printer());
psc.get<Printer>().print();
psc = Scaner(); // the printer is gone
Use some std::unique_ptr constructor:
std::unique_ptr<Power>
call(const Power &p, const int &i) {
if (i)
return std::unique_ptr<Power>(new Printer(p));
else
return std::unique_ptr<Power>(new Scanner(p));
}
Perhaps what you really want is a tagged union. Follow the rule of five. See this for inspiration.
I'm trying to implement a minheap in C++. However the following code keeps eliciting errors such as :
heap.cpp:24:4: error: cannot convert 'complex int' to 'int' in assignment
l=2i;
^
heap.cpp:25:4: error: cannot convert 'complex int' to 'int' in assignment
r=2i+1;
^
heap.cpp: In member function 'int Heap::main()':
heap.cpp:47:16: error: no matching function for call to 'Heap::heapify(int [11], int&)'
heapify(a,i);
^
heap.cpp:47:16: note: candidate is:
heap.cpp:21:5: note: int Heap::heapify(int)
int heapify(int i) //i is the parent index, a[] is the heap array
^
heap.cpp:21:5: note: candidate expects 1 argument, 2 provided
make: * [heap] Error 1
#include <iostream>
using namespace std;
#define HEAPSIZE 10
class Heap
{
int a[HEAPSIZE+1];
Heap()
{
for (j=1;j<(HEAPISZE+1);j++)
{
cin>>a[j];
cout<<"\n";
}
}
int heapify(int i) //i is the parent index, a[] is the heap array
{
int l,r,smallest,temp;
l=2i;
r=2i+1;
if (l<11 && a[l]<a[i])
smallest=l;
else
smallest=i;
if (r<11 && a[r]<a[smallest])
smallest=r;
if (smallest != i)
{
temp = a[smallest];
a[smallest] = a[i];
a[i]=temp;
heapify(smallest);
}
}
int main()
{
int i;
for (i=1;i<=HEAPSIZE;i++)
{
heapify(a,i);
}
}
}
Ultimately, the problem with this code is that it was written by someone who skipped chapters 1, 2 and 3 of "C++ for Beginners". Lets start with some basics.
#include <iostream>
using namespace std;
#define HEAPSIZE 10
Here, we have included the C++ header for I/O (input output). A fine start. Then, we have issued a directive that says "Put everything that is in namespace std into the global namespace". This saves you some typing, but means that all of the thousands of things that were carefully compartmentalized into std:: can now conflict with names you want to use in your code. This is A Bad Thing(TM). Try to avoid doing it.
Then we went ahead and used a C-ism, a #define. There are times when you'll still need to do this in C++, but it's better to avoid it. We'll come back to this.
The next problem, at least in the code you posted, is a misunderstanding of the C++ class.
The 'C' language that C++ is based on has the concept of a struct for describing a collection of data items.
struct
{
int id;
char name[64];
double wage;
};
It's important to notice the syntax - the trailing ';'. This is because you can describe a struct and declare variables of it's type at the same time.
struct { int id; char name[64]; } earner, manager, ceo;
This declares a struct, which has no type name, and variables earner, manager and ceo of that type. The semicolon tells the compiler when we're done with this statement. Learning when you need a semicolon after a '}' takes a little while; usually you don't, but in struct/class definition you do.
C++ added lots of things to C, but one common misunderstanding is that struct and class are somehow radically different.
C++ originally extended the struct concept by allowing you to describe functions in the context of the struct and by allowing you to describe members/functions as private, protected or public, and allowing inheritance.
When you declare a struct, it defaults to public. A class is nothing more than a struct which starts out `private.
struct
{
int id;
char name[64];
double wage;
};
class
{
public:
int id;
char name[64];
double wage;
};
The resulting definitions are both identical.
Your code does not have an access specifier, so everything in your Heap class is private. The first and most problematic issue this causes is: Nobody can call ANY of your functions, because they are private, they can only be called from other class members. That includes the constructor.
class Foo { Foo () {} };
int main()
{
Foo f;
return 0;
}
The above code will fail to compile, because main is not a member of Foo and thus cannot call anything private.
This brings us to another problem. In your code, as posted, main is a member of Foo. The entry point of a C++ program is main, not Foo::main or std::main or Foo::bar::herp::main. Just, good old int main(int argc, const char* argv[]) or int main().
In C, with structs, because C doesn't have member functions, you would never be in a case where you were using struct-members directly without prefixing that with a pointer or member reference, e.g. foo.id or ptr->wage. In C++, in a member function, member variables can be referenced just like local function variables or parameters. This can lead to some confusion:
class Foo
{
int a, b;
public:
void Set(int a, int b)
{
a = a; // Erh,
b = b; // wat???
}
};
There are many ways to work around this, but one of the most common is to prefix member variables with m_.
Your code runs afoul of this, apparently the original in C passed the array to heapify, and the array was in a local variable a. When you made a into a member, leaving the variable name exactly the same allowed you not to miss the fact that you no-longer need to pass it to the object (and indeed, your heapify member function no-longer takes an array as a pointer, leading to one of your compile errors).
The next problem we encounter, not directly part of your problem yet, is your function Heap(). Firstly, it is private - you used class and haven't said public yet. But secondly, you have missed the significance of this function.
In C++ every struct/class has an implied function of the same name as the definition. For class Heap that would be Heap(). This is the 'default constructor'. This is the function that will be executed any time someone creates an instance of Heap without any parameters.
That means it's going to be invoked when the compiler creates a short-term temporary Heap, or when you create a vector of Heap()s and allocate a new temporary.
These functions have one purpose: To prepare the storage the object occupies for usage. You should try and avoid as much other work as possible until later. Using std::cin to populate members in a constructor is one of the most awful things you can do.
We now have a basis to begin to write the outer-shell of the code in a fashion that will work.
The last change is the replacement of "HEAPSIZE" with a class enum. This is part of encapsulation. You could leave HEAPSIZE as a #define but you should expose it within your class so that external code doesn't have to rely on it but can instead say things like Heap::Size or heapInstance.size() etc.
#include <iostream>
#include <cstdint> // for size_t etc
#include <array> // C++11 encapsulation for arrays.
struct Heap // Because we want to start 'public' not 'private'.
{
enum { Size = 10 };
private:
std::array<int, Size> m_array; // meaningful names ftw.
public:
Heap() // default constructor, do as little as possible.
: m_array() // says 'call m_array()s default ctor'
{}
// Function to load values from an istream into this heap.
void read(std::istream& in)
{
for (size_t i = 0; i < Size; ++i)
{
in >> m_array[i];
}
return in;
}
void write(std::ostream& out)
{
for (size_t i = 0; i < Size; ++i)
{
if (i > 0)
out << ','; // separator
out << m_array[i];
}
}
int heapify(size_t index)
{
// implement your code here.
}
}; // <-- important.
int main(int argc, const char* argv[])
{
Heap myHeap; // << constructed but not populated.
myHeap.load(std::cin); // read from cin
for (size_t i = 1; i < myHeap.Size; ++i)
{
myHeap.heapify(i);
}
myHead.write(std::cout);
return 0;
}
Lastly, we run into a simple, fundamental problem with your code. C++ does not have implicit multiplication. 2i is the number 2 with a suffix. It is not the same as 2 * i.
int l = 2 * i;
There is also a peculiarity with your code that suggests you are mixing between 0-based and 1-based implementation. Pick one and stick with it.
--- EDIT ---
Technically, this:
myHeap.load(std::cin); // read from cin
for (size_t i = 1; i < myHeap.Size; ++i)
{
myHeap.heapify(i);
}
is poor encapsulation. I wrote it this way to draw on the original code layout, but I want to point out that one reason for separating construction and initialization is that it allows initialization to be assured that everything is ready to go.
So, it would be more correct to move the heapify calls into the load function. After all, what better time to heapify than as we add new values, keeping the list in order the entire time.
for (size_t i = 0; i < Size; ++i)
{
in >> m_array[i];
heapify(i);
}
Now you've simplified your classes api, and users don't have to be aware of the internal machinery.
Heap myHeap;
myHeap.load(std::cin);
myHeap.write(std::cout);
In player.h I have enum race {Living, Dead, Nature,None};
In player.cpp I have
race myRace;
void Player::addPlayer(int x)
{
cout<<"added player"<<x<<endl;
this->karma=0;
this->myTurn=false;
myRace=race(4);
}
So this should , when a player is created make myRace = None.
Now in Main.cpp I want to check a players race, how would i do this?
I tried if (player[x].myRace=None) but of course that wont work..
This should work: myRace = None; and it's the recommended way to use an enum to avoid another mistake that you made, 4 is not a valid integer option for your enum, because Living is 0 and None will be 3.
Enums should work the way you describe. Unfortunately you only provided modified, unrunnable code and no compiler errors or other output. However, the following code should show you how to use enums: (Live demo)
#include <iostream>
enum Race { None, Living, Dead, Nature}; // always put invalid as the 0 entry.
class Player
{
uint32_t m_karma;
bool m_myTurn;
Race m_myRace;
public:
void addPlayer(int x_)
{
std::cout << "added player " << x_ << std::endl;
m_karma = 0;
m_myTurn = false;
m_myRace = None;
}
};
int main(int argc, const char** argv)
{
Player fred;
fred.addPlayer(1);
return 0;
}
If you have a C++11 capable compiler you can be more specific and use "enum Class" which will force you to qualify enumerations (i.e. Race::None). (Live demo)
#include <iostream>
enum class Race { None, Living, Dead, Nature}; // always but invalid as the 0 entry.
class Player
{
uint32_t m_karma;
bool m_myTurn;
Race m_myRace;
public:
void addPlayer(int x_)
{
std::cout << "added player " << x_ << std::endl;
m_karma = 0;
m_myTurn = false;
m_myRace = Race::None;
}
};
int main(int argc, const char** argv)
{
Player fred;
fred.addPlayer(1);
return 0;
}
"player[x].race = None" won't work because that is assignment, not a test for equality. You don't say why it didn't work, I'm going to assume - if it wasn't just the wrong variable name - because it was private or inaccessible. In that case, just add a member function to return the race:
class Player {
...
public:
Race getRace() const { return m_myRace; }
...
};
The whole point of enums is to do away with magical numbers, so although enums are convertible to integers, getting enums from integers is counter productive.
You should write myRace=None, rather than myRace=4.
Secondly unless, you explicitly specify otherwise in your declaration of your enum type, enums starts at 0, so None corresponds to 3 rather than 4.
Thirdly, in C++ you don't have to write this->member_name to access a member variable. If you want to differentiate members from nonmembers, you can save many keystrokes by adopting a much shorter naming convention. (Such as appending _ to member variable names).
Finaly, = in C++ means assignment, NOT equality comparison.
if (player[x].myRace=None) effectively means player[x].myRace=None; if (player[x].myRace), i.e. the condition is always true, since player[x].myRace==None==3. Most of the time, the assignment operator inside if conditions is an error and your compiler might warn you about this.
Also, it's kind of weird for a member variable to access your myRace global (and globals are usually a bad idea). If myRace is not a global, then a function can access it only if a pointer or a reference is passed to it as an argument or if myRace is made as a member variable and your function is a method of the same class.
Be careful here ! myRace is not part of Player class. So you will have one instance of myRace, whatever the number of players.
You should make myRace part of your class. If you don't, everytime you create a new player, the race changes !
If this is what you want, it should be a static member of your player class, so you could add a static getter tro retrieve it
class Player{
static int myRace;
public:
static int GetMyRace(){
return myRace;
}
...
}
and then, access it like this :
Player::GetMyRace();
I had the following piece of code (simplified for this question):
struct StyleInfo
{
int width;
int height;
};
typedef int (StyleInfo::*StyleInfoMember);
void AddStyleInfoMembers(std::vector<StyleInfoMember>& members)
{
members.push_back(&StyleInfo::width);
members.push_back(&StyleInfo::height);
}
Now, we had to restructure this a bit, and we did something like this:
struct Rectangle
{
int width;
int height;
};
struct StyleInfo
{
Rectangle size;
};
typedef int (StyleInfo::*StyleInfoMember);
void AddStyleInfoMembers(std::vector<StyleInfoMember>& members)
{
members.push_back(&StyleInfo::size::width);
members.push_back(&StyleInfo::size::height);
}
If this all looks like a stupid thing to do, or if you feel there's a good opportunity to apply BOOST here for some reason, I must warn you that I really simplified it all down to the problem at hand:
error C3083: 'size': the symbol to the left of a '::' must be a type
The point I'm trying to make is that I don't know what the correct syntax is to use here. It might be that "StyleInfo" is not the correct type of take the address from to begin with, but in my project I can fix that sort of thing (there's a whole framework there). I simply don't know how to point to this member-within-a-member.
Remember a pointer to a member is just used like a member.
Obj x;
int y = (x.*)ptrMem;
But like normal members you can not access members of subclasses using the member access mechanism. So what you need to do is access it like you would access a member of the object (in your case via the size member).
#include <vector>
#include <iostream>
struct Rectangle
{
int width;
int height;
};
struct StyleInfo
{
Rectangle size;
};
typedef Rectangle (StyleInfo::*StyleInfoMember);
typedef int (Rectangle::*RectangleMember);
typedef std::pair<StyleInfoMember,RectangleMember> Access;
void AddStyleInfoMembers(std::vector<Access>& members)
{
members.push_back(std::make_pair(&StyleInfo::size,&Rectangle::width));
members.push_back(std::make_pair(&StyleInfo::size,&Rectangle::height));
}
int main()
{
std::vector<Access> data;
AddStyleInfoMembers(data);
StyleInfo obj;
obj.size.width = 10;
std::cout << obj.*(data[0].first).*(data[0].second) << std::endl;
}
This is not something I would recommend doing!
An alternative (that I recommend even less) is to find the byte offset from the beginning of the class and then just add this to the objects address. Obviously this will involve a lot of casting backwards and forwards so this looks even worse then the above.
Is it definitely possible? I honestly don't know, never having played much with pointer-to-member.
Suppose you were using non-POD types (I know you aren't, but the syntax would have to support it). Then pointer-to-member might have to encapsulate more than just an offset from the base pointer. There might be indirection as well, depending how multiple inheritance is implemented. With multiple levels of member indirection, this could get arbitrarily complicated, which is a lot to ask for a type that has to have fixed size.
Perhaps you need a vector of pairs, of types defined by:
typedef Rectangle (StyleInfo::*StyleInfoMember);
typedef int (Rectangle::*RectangleMember);
Apply each in turn to get where you want to be. Of course this still doesn't let you build a vector of mappings from a StyleInfo to arbitrary members-of-members-of StyleInfo, since they wouldn't all go through Rectangle. For that you may need to open a can of functors...
size (as in &StyleInfo::size::width) is not the name of a type.
try size->width or size.width instead, depending on how your 'AddStyleInfoMembers` knows about size at all.