How to cout 'this' with overloaded output? - c++

In the following example, how to refer to the current object instance to take opportunity to use the output overload?
class Shape {
private:
double _length, _width;
double straight(double value) {
if (value<0) { return -value; }
if (value==0) { return 1; }
return value;
}
public:
Shape() { setDims(1,1); }
Shape(double length, double width) {
setDims(length, width); }
void setDims(double length, double width) {
_length=straight(length); _width=straight(width); }
friend ostream &operator<<(ostream &output, Shape &S) {
output << S._length << "," << S._width; return output; }
void display() { cout << [THIS] << endl; }
};
int main(int argc, const char * argv[]) {
Shape s1; s1.display();
return 0;
}

Just like this:
void display() { cout << *this << endl; }

this is a pointer. Your operator<< wants an actual Shape object, not a pointer.
So you'll have to dereference the pointer first: *this.

Alternatively just use operator<<
#include <iostream>
using namespace std;
class Shape {
private:
double _length, _width;
double straight(double value) {
if (value<0) { return -value; }
if (value == 0) { return 1; }
return value;
}
public:
Shape() { setDims(1, 1); }
Shape(double length, double width) {
setDims(length, width);
}
void setDims(double length, double width) {
_length = straight(length); _width = straight(width);
}
friend ostream &operator<<(ostream &output, Shape &S) {
output << S._length << "," << S._width; return output;
}
int main(int argc, const char * argv[]) {
Shape s1;
std::cout << s1 << std::endl;
}

Related

Deep copy unsuccessful

might be a stupid question and if it is, let me know, I will delete it as soon as possible. The thing is I have to make a deep copy in class "Kambarys" (ignore mixed languages, I know I shouldn't do that). Program terminates after trying to call function second time. Probably the problem is my syntax in constructor copy, but I can't find the correct one anywhere. One of the requirements is to create langas, durys and kambarys in dynamic memory using "new" and delete windows vector and door in Kambarys destructor. Appreciate the help!
Requirements:
In the main method, use the new operator to create room k1, add windows and doors to it. Write a constructor Room (const Room & k) that would create a correct copy. In the method main, write another room k2. Calculate the length of the baseboards / wall area.
Perform the following steps: k2 = * k1; delete k1;
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;
class Langas{
private:
float height;
float widht;
static int countL;
public:
Langas(float h, float w){
this->height=h;
this->widht=w;
countL++;
}
~Langas(){
--countL;
}
float getHeight(){
return height;
}
float getWidht(){
return widht;
}
static int getWindowCount(){
return countL;
}
};
class Durys{
private:
float heightD;
float widhtD;
static int countD;
public:
Durys(float hD, float wD){
this->heightD=hD;
this->widhtD=wD;
countD++;
}
~Durys(){
--countD;
}
float getHeightD(){
return heightD;
}
float getWidhtD(){
return widhtD;
}
static int getDoorCount(){
return countD;
}
};
class Kambarys{
private:
float heightK;
float widhtK;
float lenghtK;
public:
vector<Langas*> windows;
Durys* door;
Kambarys(float hK, float wK, float lK){
this->heightK=hK;
this->widhtK=wK;
this->lenghtK=lK;
}
Kambarys(const Kambarys &k){
this->door=k.door;
this->windows=k.windows;
heightK=k.heightK;
widhtK=k.widhtK;
lenghtK=k.lenghtK;
}
~Kambarys(){
door=NULL;
for(int i=0; i<windows.size(); i++){
delete windows[i];
}
windows.clear();
delete door;
}
float getHeightK(){
return heightK;
}
float getWidhtK(){
return widhtK;
}
float getLenghtK(){
return lenghtK;
}
void addWindow(Langas* w){
windows.push_back(w);
}
void addDoor(Durys *d){
door=d;
}
};
float countWallPlot(Kambarys* k){
float cWPlot=(2*k->getLenghtK()*k->getHeightK())+(2*k->getWidhtK()*k->getHeightK());
for(int i=0; i<k->windows.size(); i++){
cWPlot-=((k->windows[i]->getHeight()))*(k->windows[i]->getWidht());
}
cWPlot-=((k->door->getHeightD()))*(k->door->getWidhtD());
return cWPlot;
}
float countLenght(Kambarys* k){
float floorL=(k->getLenghtK()*k->getWidhtK()*2);
floorL-=(k->door->getWidhtD());
return floorL;
}
int Langas::countL=0;
int Durys::countD=0;
int main(){
Langas *langas1=new Langas(3.4, 1.2);
Durys *durys=new Durys(3.1, 1.5);
Langas *langas2=new Langas(6.4, 1.5);
Kambarys *k=new Kambarys(30.4, 40.1, 50.1);
Kambarys *k2=k;
k->addWindow(langas1);
k->addWindow(langas2);
k->addDoor(durys);
cout<<countWallPlot(k)<<" "<<countLenght(k)<<endl;
cout<<"Window count "<<Langas::getWindowCount()<<", door count "<<Durys::getDoorCount()<<endl;
k2=k;
delete k;
cout<<countWallPlot(k2)<<" "<<countLenght(k2)<<endl;
cout<<"Window count "<<Langas::getWindowCount()<<", door count "<<Durys::getDoorCount()<<endl;
}
You have to allocate memory for k2 and copy the object, not the pointer.
You have to allocate memory in the copy constructor and copy assignment operator.
door=NULL; before delete door; would skip the delete and cause a memory leak.
windows.clear(); is not necessary in the destructor. Keep your code simple.
EDIT: After you added "Perform the following steps: k2 = * k1; delete k1;" I made k2 an object, not a pointer.
#include <iostream>
#include <vector>
class Langas {
private:
float height;
float width;
static int count;
public:
Langas(float h, float w): height(h), width(w) {
++count;
}
~Langas() { --count; }
float getHeight() const { return height; }
float getWidht() const { return width; }
static int getWindowCount() { return count; }
};
class Durys {
private:
float height;
float width;
static int count;
public:
Durys(float h, float w): height(h), width(w) {
++count;
}
~Durys() { --count; }
float getHeight() const { return height; }
float getWidth() const { return width; }
static int getDoorCount() { return count; }
};
class Kambarys {
private:
float height;
float width;
float length;
public:
std::vector<Langas *> windows;
Durys *door = nullptr;
Kambarys(float hK, float wK, float lK): height(hK), width(wK), length(lK) {}
Kambarys(const Kambarys &k): height(k.height), width(k.width), length(k.length), windows(), door(k.door ? new Durys(k.door->getHeight(), k.door->getWidth()) : nullptr) {
for (const auto window : k.windows) {
windows.emplace_back(new Langas(window->getHeight(), window->getWidht()));
}
}
Kambarys &operator=(const Kambarys &k) {
door = k.door ? new Durys(k.door->getHeight(), k.door->getWidth()) : nullptr;
for (const auto window : k.windows) {
windows.emplace_back(new Langas(window->getHeight(), window->getWidht()));
}
height = k.height;
width = k.width;
length = k.length;
return *this;
}
~Kambarys() {
for (auto window : windows) {
delete window;
}
delete door;
}
float getHeight() const { return height; }
float getWidth() const { return width; }
float getLength() const { return length; }
void addWindow(Langas *w) { windows.emplace_back(w); }
void addDoor(Durys *d) { door = d; }
};
float countWallPlot(const Kambarys &k) {
float cWPlot = 2 * k.getLength() * k.getHeight() + 2 * k.getWidth() * k.getHeight();
for (const auto window : k.windows) {
cWPlot -= window->getHeight() * window->getWidht();
}
cWPlot -= k.door->getHeight() * k.door->getWidth();
return cWPlot;
}
float countLength(const Kambarys &k) {
float floor = k.getLength() * k.getWidth() * 2;
floor -= k.door->getWidth();
return floor;
}
int Langas::count = 0;
int Durys::count = 0;
int main() {
Langas *langas1 = new Langas(3.4, 1.2);
Durys *durys = new Durys(3.1, 1.5);
Langas *langas2 = new Langas(6.4, 1.5);
Kambarys *k = new Kambarys(30.4, 40.1, 50.1);
Kambarys k2(*k);
k->addWindow(langas1);
k->addWindow(langas2);
k->addDoor(durys);
std::cout << countWallPlot(*k) << " " << countLength(*k) << std::endl;
k2 = *k;
std::cout << "Window count " << Langas::getWindowCount() << ", door count " << Durys::getDoorCount() << std::endl;
delete k;
std::cout << countWallPlot(k2) << " " << countLength(k2) << std::endl;
std::cout << "Window count " << Langas::getWindowCount() << ", door count " << Durys::getDoorCount() << std::endl;
}

Get "Trigger Breakpoint Error at delete" when using template

I'm using visual studio.
I have 3 class.
It's ok when I try to print Rectangle ABCD, but when i push ABCD into Array [rectangle] A and try to print ABCD again, the "wntdll.pdb not loaded" appear and i continue, it's "triggers breakpoint error!!" at delete in ~Rectangle()
I know it's something up to the pointer in class Rectangle but can't firgure out.
`int main(){
Array<Rectangle>A;
Rectangle a;
cout << a; //It's oke
A.PushBack(a); // problem here
cout<<a;
}`
class Point
{
private:
float _x;
float _y;
public:
float GetX() { return _x; }
float GetY() { return _y; }
public:
Point();
Point(float, float);
Point(const Point&);
~Point() {};
public:
string ToString() const;
public:
friend istream& operator>>(istream&, Point*);
friend ostream& operator<<(ostream&, const Point&);
};
Point::Point() {
_x = 1;
_y = 1;
}
Point::Point(float x, float y) {
_x = x;
_y = y;
}
Point::Point(const Point& a) {
_x = a._x;
_y = a._y;
}
string Point::ToString() const{
stringstream out;
out << "( " << _x << "," << _y << " )";
return out.str();
}
istream& operator>>(istream& in, Point* a) {
cout << "Nhap x: ";
in >> a->_x;
cout << "Nhap y: ";
in >> a->_y;
return in;
}
ostream& operator<<(ostream& out, const Point& a)
{
out << a.ToString();
return out;
}
```
class Rectangle
{
private:
Point* _topleft;
Point* _botright;
public:
void Set_topleft(Point tl) { _topleft = &tl; }
Point Get_topleft() { return *_topleft; }
void Set_botright(Point br) { _botright = &br; }
Point Get_botright() { return *_botright; }
public:
Rectangle();
Rectangle(Point*, Point*);
~Rectangle();
public:
string ToString() const;
public:
friend istream& operator>>(istream&, Rectangle&);
friend ostream& operator<<(ostream&, const Rectangle&);
};
Rectangle::Rectangle()
{
_topleft = new Point(0, 2);
_botright = new Point(3, 0);
}
Rectangle::Rectangle(Point* a, Point* b)
{
_topleft = new Point(*a);
_botright = new Point(*b);
}
Rectangle::~Rectangle()
{
delete _topleft;
delete _botright;
}
string Rectangle::ToString() const
{
stringstream out;
out << "A" << *_topleft << "+" << "D" << *_botright;
return out.str();
}
istream& operator>>(istream& in, Rectangle& a)
{
std::cout << "A( x,y ): ";
in >> a._topleft;
std::cout << "D( x,y ): ";
in >> a._botright;
return in;
}
ostream& operator<<(ostream& out, const Rectangle& a)
{
out << a.ToString();
return out;
}
```
template<class T>
class Array
{
private:
T* _a;
int _len;
public:
Array();
~Array();
public:
int length() { return _len; }
void PushBack(T);
T GetAt(int);
};
template<class T>
Array<T>::Array() {
_a = new T[128];
_len = 0;
}
template<class T>
Array<T>::~Array() {
delete[] _a;
_len = 0;
}
template<class T>
void Array<T>::PushBack(T value) {
if (_len >= 128)
{
std::cout << "Array is over size, which is 128\n";
return;
}
_a[_len] = value;
_len++;
}
template<class T>
T Array<T>::GetAt(int pos) {
return _a[pos];
}
```
The problem in your code is that when you PushBack the Rectangle object a into the array, you create copy of this object. This means that you just copy pointers _topleft and _botright. So in this part of code, you have 2 objects with the same pointers, so you're trying to delete twice the same part of memory.
To fix this you need to define own copy constructor, which will create new pointers in the new object.
Remember also to define own move constructors or make it disable for your class.
Rectangle(const Rectangle &other)
{
if(other._topleft)
_topleft= new Point(*other._topleft);
else
_topleft = nullptr;
if(other._botright)
_botright= new Point(*other._botright);
else
_topleft = nullptr;
}
The next problem is because of definition of void Array<T>::PushBack(T value). Please change it to the void Array<T>::PushBack(const T& value).
Also, try Rectangle(Rectangle&& o) = delete;

no instance of overloaded function "search" matches the argument list

I have the following problem with my search function.
It expects 3 parameters, and one of them is something like const rational_t* v. I want to pass a vector through that parameter but it doesnt seems to work..
Code:
#include <iostream>
#include <cmath>
#include <vector>
#include "rational_t.hpp"
using namespace std;
bool search(const rational_t* v, const int n, const rational_t& x)
{
for(int i = 0; i < n; i++) {
if(v[i].value() == x.value()) {
return true;
} else {
return false;
}
}
};
int main()
{
rational_t a(1, 2), b(3), c, d(1, 2);
vector<rational_t> v;
v.push_back(a);
v.push_back(b);
v.push_back(c);
cout << "a.value()= " << a.value() << endl;
cout << "b.value()= " << b.value() << endl;
cout << "c.value()= " << c.value() << endl;
cout << search(v, v.size(), d); // Problem here
return 0;
}
I´ve also tried cout << search(v&, v.size(), d); with the reference &.
Any ideas? Thank You.
The class :
#pragma once
#include <iostream>
#include <cassert>
#include <cmath>
#define EPSILON 1e-6
using namespace std;
class rational_t
{
int num_, den_;
public:
rational_t(const int = 0, const int = 1);
~rational_t() {}
int get_num() const
{
return num_;
}
int get_den() const
{
return den_;
}
void set_num(const int n)
{
num_ = n;
}
void set_den(const int d)
{
assert(d != 0), den_ = d;
}
double value(void) const;
rational_t opposite(void) const;
rational_t reciprocal(void) const;
bool equal(const rational_t &r, const double precision = EPSILON) const;
bool greater(const rational_t &r, const double precision = EPSILON)
const;
bool less(const rational_t &r, const double precision = EPSILON) const;
bool cero_equal(const double precision) const;
void write(ostream &os = cout) const;
void read(istream &is = cin);
};
The first argument of search should be a rational_t* but you're passing a vector<rational_t>.
You want
search(v.data(), v.size(), d)
instead of
search(v, v.size(), d)
But I'd write this like this which is cleaner IMO:
bool search(vector<rational_t> & v, const rational_t& x)
{
for (int i = 0; i < v.size(); i++) {
if (v[i].value() == x.value()) {
return true;
}
else {
return false;
}
}
}
...
cout << search(v, d);

How to use overloaded ostream operator with array of pointers to objects?

In the code bellow, instead of using new function "void print()", how can I use the overloaded "<<" operator in order to print the required information?
Or to be exact, where is the mistake here?
Overloaded << operator in one of the inherited classes:
friend ostream &operator<<(ostream &os, DigitSecret &s){
for(int i=0;i<s.n;i++)
os<<s.digits[i];
return os<<" Simple entropy: "<<s.simpleEntropy()<<" Total: "<<s.total();
}
void printAll (Secret ** secrets, int n) {
for(int i=0;i<n;i++){
cout<<secret[i] //This is printing an address, however that is not what i want.
secrets[i]->print(); //I want that to work like this.
}
}
The whole code: https://pastebin.com/MDCsqUxJ
I want line 134 and 143 to work correctly.
EDIT:
secret[i] is of type Secret*, you should derefence first and then your overload will get picked:
cout << *secret[i];
Side note: use std::vector instead of raw dynamic allocation.
See this snippet:
class base {
public:
virtual void print() = 0;
virtual std::ostringstream get_value() const = 0;
int get_id() const { return id_; }
protected:
int id_;
};
class A:public base {
public:
A(std::string val):val_(val){ id_ = 1; }
void print() override { std::cout << " I am A" << std::endl; }
std::ostringstream get_value() const { std::ostringstream ss; ss << val_; return ss; }
private:
std::string val_;
};
class B :public base {
public:
B(int val):val_(val) { id_ = 2; }
void print() override { std::cout << " I am B" << std::endl; }
virtual std::ostringstream get_value() const { std::ostringstream ss; ss << val_; return ss; }
private:
int val_;
};
std::ostream& operator << (std::ostream& os, const base* p)
{
std::string str;
if (p->get_id() == 1) {
str = ((A*)(p))->get_value().str();
os << "A " << str << "\n";
}
else
if (p->get_id() == 2) {
str = ((B*)(p))->get_value().str();
os << "B " << str << "\n";
}
return os;
}
void PrintAll(base** a)
{
for (int i = 0; i<2; i++)
std::cout << a[i];
}
int main()
{
base* a[2];
a[0] = new A("Hello");
a[1] = new B(10);
PrintAll(a);
return 0;
}
Output:
I Solved it this way:
void printAll (Secret ** secrets, int n) {
for(int i=0;i<n;i++){
DigitSecret* ds = NULL;
CharSecret* cs = NULL;
ds = dynamic_cast<DigitSecret*>(secrets[i]);
cs = dynamic_cast<CharSecret*>(secrets[i]);
if(ds!=NULL)
cout<<*ds<<endl;
else
cout<<*cs<<endl;
// secrets[i]->print();
}
}
Basically in this case, I have to use dynamic_cast with new pointer from the derived class, on each pointer from the array, and check if the pointer is !=NULL, and then use the overloaded operator on the dereferenced new pointer.

Copying object from a superclass pointer

Suppose I have two classes a base class and an inherited class as follows:
class Magic : public Attack
{
public:
Magic(int uID, std::string &name) : Attack(ActionType::MagicAction, uID, name)
{
}
};
class MacroMagic : public Magic
{
MacroMagic(int uID) : Magic(uID, std::string("Testing"))
{
}
void PreUse() override
{
std::cout << "Test" << std::endl;
}
}
I have a shared_ptr to an instance of magic that I would like to copy, but at runtime I will not know whether that pointer points to an instance of Magic, MacroMagic or anything that may have inherited from Magic. I want to be able to copy the object pointed to by the shared_ptr like so:
Battles::magic_ptr mgPtr = MagicNameMap[name];
if (mgPtr.get() != nullptr)
{
return magic_ptr(new Magic(*mgPtr));
}
return mgPtr;
where magic_ptr is a typedef for a shared_ptr around the Magic Class. I could do it by specifying a virtual copy function and calling that, but I'd like to make it less obtuse and easier to maintain. I assume I can do this by a copy constructor, but I'm unsure how to in this instance. The way I have it now, the pointer returned by the above code will not call the override pReUse() function.
A bit of guidance would be much appreciated, thanks
I could do it by specifying a virtual copy function and calling that, but I'd like to make it less obtuse and easier to maintain.
you're working against the language.
you could accomplish what you are after, but i don't recommend it, and it is certainly not easier to setup or maintain than virtual Magic* clone() = 0.
perhaps you could outline the problem that brought you to this conclusion, and then we can help from there. there are usually alternatives which don't fight the language.
EDIT
here's a way around it using an external function table (t_magic_operation_table). you can apply and create several function tables and keep them around. since they exist in the magic object as a single pointer, then you can make these tables quite large (if needed). if your magic types can use the same data/members, then that is one approach. be careful: i threw this together suuuper-fast. it demonstrates the technique, but it's pretty bad otherwise:
#include <iostream>
#include <string>
namespace MONSpiel {
inline unsigned prndm(const unsigned& max) {
return 1 + arc4random() % max;
}
class t_ghoul;
class t_biclops;
class t_magic;
class t_hero {
t_hero();
t_hero(const t_hero&);
t_hero& operator=(const t_hero&);
public:
t_hero(const std::string& inName) : d_name(inName) {
}
const std::string& name() const {
return this->d_name;
}
template<typename TEnemy, typename TMagic>
void attack(TEnemy& enemy, TMagic& magic) const {
if (enemy.isDead()) {
return;
}
enemy.hit(magic.power());
if (enemy.isDead()) {
std::cout << this->name() << ": see you in the prequel...\n\n";
}
else {
std::cout << this->name() << ": have you had enough " << magic.name() << ", " << enemy.name() << "???\n\n";
}
}
/* ... */
private:
const std::string d_name;
};
class t_enemy {
t_enemy();
t_enemy(const t_enemy&);
t_enemy& operator=(const t_enemy&);
public:
t_enemy(const std::string& inName) : d_name(inName), d_lifePoints(1000) {
}
virtual ~t_enemy() {
}
const std::string& name() const {
return this->d_name;
}
bool isDead() const {
return 0 >= this->d_lifePoints;
}
const int& lifePoints() const {
return this->d_lifePoints;
}
void hit(const int& points) {
this->d_lifePoints -= points;
}
/* ... */
private:
const std::string d_name;
int d_lifePoints;
};
class t_ghoul : public t_enemy {
public:
static int MaxDaysAwake() {
return 100;
}
t_ghoul(const std::string& inName) : t_enemy(inName), d_bouyancy(prndm(100)), d_proximityToZebra(prndm(100)), d_daysAwake(prndm(MaxDaysAwake())) {
}
const int& bouyancy() const {
return this->d_bouyancy;
}
const int& proximityToZebra() const {
return this->d_proximityToZebra;
}
const int& daysAwake() const {
return this->d_daysAwake;
}
private:
int d_bouyancy;
int d_proximityToZebra;
int d_daysAwake;
};
class t_biclops : public t_enemy {
public:
t_biclops(const std::string& inName) : t_enemy(inName), d_isTethered(prndm(2)), d_amountOfSunblockApplied(prndm(100)) {
}
const bool& isTethered() const {
return this->d_isTethered;
}
const int& amountOfSunblockApplied() const {
return this->d_amountOfSunblockApplied;
}
private:
bool d_isTethered;
int d_amountOfSunblockApplied;
};
class t_magic_operation_table {
public:
typedef void (*t_ghoul_skirmish_function)(t_magic&, t_ghoul&);
typedef void (*t_biclops_skirmish_function)(t_magic&, t_biclops&);
t_magic_operation_table(t_ghoul_skirmish_function ghoulAttack, t_biclops_skirmish_function biclopsAttack) : d_ghoulAttack(ghoulAttack), d_biclopsAttack(biclopsAttack) {
}
void willSkirmish(t_magic& magic, t_ghoul& ghoul) const {
this->d_ghoulAttack(magic, ghoul);
}
void willSkirmish(t_magic& magic, t_biclops& biclops) const {
this->d_biclopsAttack(magic, biclops);
}
private:
t_ghoul_skirmish_function d_ghoulAttack;
t_biclops_skirmish_function d_biclopsAttack;
};
class t_action {
public:
typedef enum t_type {
NoAction = 0,
MagicAction,
ClubAction,
ClassAction
} t_type;
};
class t_attack {
public:
t_attack(const t_action::t_type& actionType, const int& uID, const std::string& inName) : d_actionType(actionType), d_uID(uID), d_name(inName) {
}
virtual ~t_attack() {
}
void reset() {
/* ... */
}
const std::string& name() const {
return this->d_name;
}
private:
t_action::t_type d_actionType;
int d_uID;
std::string d_name;
};
class t_magic : public t_attack {
t_magic();
t_magic(const t_magic&);
t_magic& operator=(const t_magic&);
static void GhoulSkirmishA(t_magic& magic, t_ghoul& ghoul) {
magic.d_accuracy = ghoul.bouyancy() + prndm(16);
magic.d_power = ghoul.proximityToZebra() + prndm(43);
}
static void GhoulSkirmishB(t_magic& magic, t_ghoul& ghoul) {
magic.d_accuracy = ghoul.bouyancy() / magic.flammability() + prndm(32);
magic.d_power = t_ghoul::MaxDaysAwake() - ghoul.daysAwake() + prndm(23);
}
static void BiclopsSkirmishA(t_magic& magic, t_biclops& biclops) {
if (biclops.isTethered()) {
magic.d_accuracy = 90 + prndm(16);
}
else {
magic.d_accuracy = 40 + prndm(11);
}
magic.d_power = biclops.amountOfSunblockApplied() + prndm(17);
}
static void BiclopsSkirmishB(t_magic& magic, t_biclops& biclops) {
if (biclops.isTethered()) {
magic.d_accuracy = 80 + prndm(80);
}
else {
magic.d_accuracy = 50 + prndm(50);
}
magic.d_power = 80 + prndm(30);
}
const t_magic_operation_table* NextOperationTable() {
static const t_magic_operation_table tables[4] = {
t_magic_operation_table(GhoulSkirmishA, BiclopsSkirmishA),
t_magic_operation_table(GhoulSkirmishB, BiclopsSkirmishB),
t_magic_operation_table(GhoulSkirmishB, BiclopsSkirmishA),
t_magic_operation_table(GhoulSkirmishA, BiclopsSkirmishB)
};
return & tables[arc4random() % 4];
}
public:
t_magic(const int& uID, const std::string& inName) : t_attack(t_action::MagicAction, uID, inName), d_power(-1), d_accuracy(-1), d_operationTable(0) {
}
int flammability() const {
return prndm(73);
}
int power() const {
return this->d_power;
}
void reset() {
t_attack::reset();
this->d_power = -1;
this->d_accuracy = -1;
this->d_operationTable = 0;
}
private:
/* assigns this->d_operationTable */
void updateOperationTableForAttack() {
this->d_operationTable = NextOperationTable();
}
public:
void heroWillAttack(const t_hero& hero, t_ghoul& ghoul) {
this->updateOperationTableForAttack();
this->d_operationTable->willSkirmish(*this, ghoul);
std::cout << hero.name() << " vs. " << ghoul.name() << "(lp:" << ghoul.lifePoints() << ")";
this->printState();
}
void heroWillAttack(const t_hero& hero, t_biclops& biclops) {
this->updateOperationTableForAttack();
this->d_operationTable->willSkirmish(*this, biclops);
std::cout << hero.name() << " vs. " << biclops.name() << "(lp:" << biclops.lifePoints() << ")";
this->printState();
}
void printState() {
std::cout << ": Magic { Power: " << this->d_power << ", Accuracy: " << this->d_accuracy << ", Operation Table: " << this->d_operationTable << "}\n";
}
private:
int d_power;
int d_accuracy;
const t_magic_operation_table* d_operationTable;
};
template<typename TEnemy>
void AttackEnemyWithMagic(t_hero& hero, TEnemy& enemy, t_magic& magic) {
if (!enemy.isDead()) {
magic.heroWillAttack(hero, enemy);
hero.attack(enemy, magic);
magic.reset();
}
}
inline void PlayIt() {
t_hero zoe("Zoe");
t_hero aragosta("Aragosta");
t_ghoul ghoul0("Al Paca");
t_ghoul ghoul1("Spud");
t_ghoul ghoul2("Sleepy");
t_biclops biclops("Scimpanzè");
t_magic hemlock(59, "hemlock");
t_magic babyPowder(91, "baby powder");
for (size_t idx(0); idx < 1000; ++idx) {
AttackEnemyWithMagic(zoe, ghoul1, hemlock);
AttackEnemyWithMagic(aragosta, biclops, babyPowder);
AttackEnemyWithMagic(zoe, ghoul2, hemlock);
AttackEnemyWithMagic(aragosta, ghoul0, babyPowder);
}
}
} /* << MONSpiel */
int main(int argc, char* const argv[]) {
#pragma unused(argc)
#pragma unused(argv)
MONSpiel::PlayIt();
return 0;
}
another option is to simply create stores (e.g. a vector), each with a different magic type. then fill a vector to point to objects in those stores. that way, you can just create one contiguous allocation for each type and randomize and weigh as needed. this is useful if your magic objects' sizes vary considerably.