I have quite a blocking problem which I don't understand. Generally, I'm making a kind of anthill simulation. There is one main passage inside divided into segments and from some of the segments ants can enter into chambers. All of these three classes (Passage, Segment, Chamber) have one common thing - collection of ants currently visiting them. So there is an abstract class AntHolder, which contains vector<Ant*> (only members relevant to the case are shown):
class AntHolder
{
protected:
std::vector<Ant*> ants;
/* some other members here */
public:
virtual bool antEnter(Ant* ant) = 0;
/* some other functions here */
};
The antEnter function is implemented differently in derived classes, but generally serves the purpose of adding ant to the ants. From the derived classes particularly I'm interested in AntChamber class (here also less important members were omitted):
class AntChamber : public AntHolder
{
protected:
int itemCapacity;
int additionalCapacity;
std::vector<Item*> items;
bool hasFood;
bool hasEgg;
public:
bool putItem(Item* item);
virtual bool antEnter(Ant* ant);
};
The putItem function is similar to the antEnter function, but it adds Item objects to items collection. (Items are e.g. food, which are moved by ants from one chamber to another.) Below there is shown implementation of both functions:
bool AntChamber::antEnter(Ant* ant)
{
if (items.size() + ants.size() == itemCapacity + additionalCapacity) return false;
ants.push_back(ant);
return true;
}
bool AntChamber::putItem(Item* item)
{
if (items.size() == itemCapacity ||
items.size() + ants.size() == itemCapacity + additionalCapacity)
return false;
if (item->getItemKind() == Food) hasFood = true; // Food == enum value
else if (item->getItemKind() == Egg) hasEgg = true; // Egg == enum value
items.push_back(item);
return true;
}
You can clearly see, that they're almost identical. But when it comes to their effect, there is crucial, surprising difference, and that is the core of my problem.
Let's say I already have an AntChamber* chamber constructed. When I run the following piece of code:
Item* item = new Item(Food);
chamber->putItem(item);
, then after that both item and chamber->items.back() points to some memory with this object. But when I run the analogous piece of code:
Ant* ant = new Ant(chamber);
chamber->antEnter(ant));
, then after that ant point to the object, but chamber->ants.back() points to NULL!
I absolutely can't understand what is going on, especially, that both putItem and antEnter in fact do the same thing: push_back the pointer, which was passed by parameter. I have already tried to simulate such case in some simplier code, like:
class A { };
class B { };
class C
{
vector<A*> va;
vector<B*> vb;
public:
A* vaBack() { return va.back(); }
B* vbBack() { return vb.back(); }
void addA(A* a) { va.push_back(a); }
void addB(B* b) { vb.push_back(b); }
};
int main(int argc, char** argv)
{
A* a = new A();
B* b = new B();
C* c = new C();
cout << (unsigned int)a << endl;
c->addA(a);
cout << (unsigned int)c->vaBack() << endl;
cout << (unsigned int)b << endl;
c->addB(b);
cout << (unsigned int)c->vbBack() << endl;
delete c;
delete b;
delete a;
}
, but it appears to work just fine - none of pointers is 0x000000.
Oh My God, I'm sooo blind...
I did SSCCE, as Shafik Yaghmour advised and I noticed the problem while doing it.
I used a mental leap, saying, that chamber->items.back() or chamber->ants.back() are NULL, because in fact, they weren't! But they're protected in their classes, so I wrote in both classes a function to get to i-th item/ant. The problem was this function. It made a standard idiotproof protection against giving index out of vector's bonds, but made a mistake doing so:
if (idx < 0 || ants.size() >= idx) return 0; // SHOULD BE <= !!!
return ants[idx];
so it always returned 0... And I looked at this method maybe hundreds of times when looking for this problem, and never noticed anything wrong (till now).
Stupid mistake... Thank you very much Shafik.
Related
I'm trying to create a mechanic that fills a vector with Spell objects, each with its own name, then select the spell with cin input and cast it on a target. What's the best way to do it? This is what I've done, but what if the spell has multiple spell effects?
//Spell.h
class Spell
{
public:
enum e_spellType //enum with all spells
{
FIREBALL = 1,
FROSTBOLT
};
enum e_spellEffect //enum with different effects
{
DAMAGE = 1, //for damaging effect
SLOW
};
Spell(e_spellEffect effect);
void returnSpellEffect(Unit* target);
//getters here
string getSpellName() const { return m_SpellName; }
int getSpellValue() const { return m_SpellValue; }
int getCooldown() const { return m_Cooldown; }
int getManaCost() const { return m_ManaCost; }
protected:
string m_SpellName;
int m_SpellValue;
int m_Cooldown;
int m_ManaCost;
int m_SpellID;
e_spellEffect m_spellEffect;
e_spellType m_spellType;
};
Spell::Spell(e_spellType type)
{
m_spellType = type;
switch (m_spellType)
{
case 1: //Fireball
m_SpellValue = 35;
m_ManaCost = 40;
m_Cooldown = 2;
m_spellEffect = DAMAGE;
case 2: //Frostbolt
m_SpellValue = 30;
m_ManaCost = 40;
m_Cooldown = 2;
m_spellEffect = SLOW;
}
}
void Spell::returnSpellEffect(Unit * target)
{
switch (m_SpellEffect)
{
case DAMAGE:
target->takeDamage(m_SpellValue);
break;
case SLOW:
target->setDamage(0.5); //modifies Unit object's attack dmg to half
break;
default:
break;
}
}
//Game.h
class Game
{
public:
void enemyCombat();
protected:
Player *player;
vector<Enemy*> enemyList;
vector<Spell*> spellList;
};
void Game::enemyCombat()
{
//after you have chosen a target from enemyList (enemyList[target])
spellList.push_back(new Spell(FIREBALL));
spellList.push_back(new Spell(FROSTBOLT));
cout << "Choose a spell to cast:" << endl
<< "1. Fireball" << endl
<< "2. Frostbolt" << endl;
int spellChoice = 0;
cin >> spellChoice;
spellList[spellChoice-1]->returnSpellEffect(enemyList[target]);
}
How do I make this whole thing more abstract to allow a spell to use more than one spell effect?
Consider using polymorphism. If you have a virtual function doSpellEffects, you can implement "usual" logic in the base class, and more specialized logic in other classes for specific spells or spell categories.
class Spell
{
public:
// Copying disabled to avoid slicing.
Spell(const Spell&) = delete;
Spell& operator=(const Spell&) = delete;
virtual ~Spell() = default;
enum e_spellType { /*...*/ };
// TBD whether e_spellEffect belongs in Spell or SimpleSpell.
// Factory function:
static std::unique_ptr<Spell> create(e_spellType spellType);
const std::string& getSpellName() const noexcept { return m_SpellName; }
int getCooldown() const noexcept { return m_Cooldown; }
int getManaCost() const noexcept { return m_ManaCost; }
virtual void doSpellEffects(Unit* target) = 0;
protected:
Spell(e_spellType spellType) :
m_spellType(spellType), m_SpellName(),
m_Cooldown(0), m_ManaCost(0) {}
e_spellType m_spellType;
std::string m_SpellName;
int m_Cooldown;
int m_ManaCost;
};
class SimpleSpell : public Spell
{
public:
SimpleSpell(e_spellType spellType);
void doSpellEffects(Unit* target) override;
int getSpellValue() const { return m_SpellValue; }
protected:
e_spellEffect m_spellEffect;
int m_SpellValue;
};
class WarlocksRay : public Spell
{
public:
WarlocksRay() : Spell(WARLOCKS_RAY, "Warlock's Ray") {}
void doSpellEffects(Unit* target) override;
};
void WarlocksRay::doSpellEffects(Unit* target)
{
// Two effects!
target->takeDamage(5);
target->stun();
}
// The factory function that creates all spells:
std::unique_ptr<Spell> Spell::create(e_spellType spellType) {
switch(spellType) {
case FIREBALL:
case FROSTBOLT:
return std::make_unique<SimpleSpell>(spellType);
case WARLOCKS_RAY:
return std::make_unique<WarlocksRay>();
}
// Invalid spellType: Log an error? Throw an exception? Just return nullptr?
throw std::invalid_argument("Bad spellType in Spell::create");
}
You could use subclassing in other ways, which might or might not be worth it:
Instead of a switch in SimpleSpell::doSpellEffects, create classes for each common effect type, like DamageSpell and SlowSpell.
If the "cooldown" and/or "mana cost" mechanics might not apply to all spells, move these members and related logic out of Spell into a class NormalCastingSpell or something, which would come between Spell and other classes in the heirarchy.
Even go so far as to create a class for each individual spell. In some cases, this could just inherit SimpleSpell or DamageSpell or etc., and the only member it would need to define would be a constructor that correctly sets all data members.
aschepler's answer is probably the most flexible one, in worst case, though, you might end up in implementing every spell on its own. A variation of could be:
a base class Effect
deriving classes DamageEffect, SlowEffect, ...
one single Spell class
The spell class then might look like this:
class Spell
{
std::string name;
std::vector<std::unique_ptr<Effect>> effects;
public:
void cast(Unit& target)
{
for(auto& effect : effects)
effect->applyTo(target);
}
}
When the spell gets casted, you likely would want to show some appropriate visual effect. You could again have polymorphic objects for these and provide one to the spell class as a member (several similar spells could re-use the same animation that way), alternatively you could have an animation for every effect and use the one of the first element in the effects vector.
Side note: You might create every spell just once in some global vector (not getting changed after creation any more, so no re-allocations – best have it const), units being able to cast spells would then just have pointers to those in their own vector.
I come from C/C# language and now I'm trying to learn about C++ and his standards functions.
Now, I'm creating a class called IMonsterDead. I will have a std::vector<IMonsterDead*> with N monsters.
Example:
class IMonsterDead {
public:
IMonsterDead(int Id)
{
this->_Id = Id;
}
virtual void OnDead() = 0;
int Id() const {
return _Id;
}
private:
int _Id;
};
One class which implements that class:
class MonsterTest : public IMonsterDead {
public:
MonsterTest(int generId)
: IMonsterDead(generId)
{
}
virtual void OnDead()
{
std::cout << "MonsterTesd died" << std::endl;
}
};
Ok, if I access directly everything works fine. But I'm trying to use std::find.
Full program test:
int main()
{
std::vector<IMonsterDead*> monsters;
for (int i = 0; i < 1000; i++)
{
monsters.emplace_back(new MonsterTest(1000 + i));
}
int id = 1033;
std::vector<IMonsterDead*>::iterator result = std::find(monsters.begin(), monsters.end(), [id]( IMonsterDead const* l) {
return l->Id() == id;
});
if (result == monsters.end())
std::cout << "Not found" << std::endl;
else
{
// Here I want to access OnDead function from result
}
return 0;
}
So I need to access OnDead function from result but I can't. Intellisense doesn't show anything for me. The result exists.
How can I access that function? Have another better way to do that?
You need to use std::find_if() instead of std::find(). std::find() is for finding an element with a specific value, so you have to pass it the actual value to find, not a user_defined predicate. std::find_if() is for finding an element based on a predicate.
Either way, if a match is found, dereferencing the returned iterator will give you a IMonsterDead* pointer (more accurately, it will give you a IMonsterDead*& reference-to-pointer). You need to then dereference that pointer in order to access any members, like OnDead().
You are also leaking memory. You are not delete'ing the objects you new. And when dealing with polymorphic types that get deleted via a pointer to a base class, the base class needs a virtual destructor to ensure all derived destructors get called properly.
With that said, you are clearly using C++11 or later (by the fact that you are using vector::emplace_back()), so you should use C++11 features to help you manage your code better:
You should use std::unique_ptr to wrap your monster objects so you don't need to delete them manually.
You should always use the override keyword when overriding a virtual method, to ensure you override it properly. The compiler can catch more syntax errors when using override than without it.
You should use auto whenever you declare a variable that the compiler can deduce its type for you. Especially useful when dealing with templated code.
Try something more like this:
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
class IMonsterDead {
public:
IMonsterDead(int Id)
: m_Id(Id)
{
}
virtual ~IMonsterDead() {}
virtual void OnDead() = 0;
int Id() const {
return m_Id;
}
private:
int m_Id;
};
class MonsterTest : public IMonsterDead {
public:
MonsterTest(int generId)
: IMonsterDead(generId)
{
}
void OnDead() override
{
std::cout << "MonsterTest died" << std::endl;
}
};
int main()
{
std::vector<std::unique_ptr<IMonsterDead>> monsters;
for (int i = 0; i < 1000; i++)
{
// using emplace_back() with a raw pointer risks leaking memory
// if the emplacement fails, so push a fully-constructed
// std::unique_ptr instead, to maintain ownership at all times...
monsters.push_back(std::unique_ptr<IMonsterDead>(new MonsterTest(1000 + i)));
// or:
// std::unique_ptr<IMonsterDead> monster(new MonsterTest(1000 + i));
// monsters.push_back(std::move(monster));
// or, if you are using C++14 or later:
// monsters.push_back(std::make_unique<MonsterTest>(1000 + i));
}
int id = 1033;
auto result = std::find_if(monsters.begin(), monsters.end(),
[id](decltype(monsters)::value_type &l) // or: (decltype(*monsters.begin()) l)
{
return (l->Id() == id);
}
// or, if you are using C++14 or later:
// [id](auto &l) { return (l->Id() == id); }
);
if (result == monsters.end())
std::cout << "Not found" << std::endl;
else
{
auto &monster = *result; // monster is 'std::unique_ptr<IMonsterDead>&'
monster->OnDead();
}
return 0;
}
Iterators are an interesting abstraction, in this case to be reduced to pointers.
Either you receive the pointer to the element or you get an invalid end.
You can use it as a pointer: (*result)->func();
You can also use it to create a new variable:
IMonsterDead &m = **result;
m.func();
This should give the same assembly, both possible.
I have code like this:
class Human
{
protected:
int age;
std::string sex;
public:
virtual void speak() = 0;
};
class Child:public Human
{
public:
void speak(){std::cout << "I am Child\n";}
};
class Man:public Human
{
public:
void speak(){std::cout << "I am Man\n";}
};
class Woman:public Human
{
public:
void speak(){std::cout << "I am Woman\n";}
};
(don't know, std::shared_ptr<Human> maybe?) operator*(std::shared_ptr<Child> &b, int x)
{
b->setAge(b->getAge()+x);
if(b->getAge()>18 && b->getSex()=="Man")
{
return (i want b to become std::shared_ptr<Man>)
}
if(b->getAge()>18 && b->getSex()=="Woman")
{
return (here I want b to become std::shared_ptr<Woman>);
}
return;
}
int main(){
auto x = std::make_shared<Child>;
x*19;
}
I know it seems odd, but it's the simplest case i can think of, without having to write down all code i'm struggling with rn. Could someone explain, what type should overload be and how to change shared_ptr type, knowing they derive from same parent?
Objects cannot change type. A Child object will always be a Child object. What you can do is create a new object with the properties you want and return that:
std::shared_ptr<Human> operator*(std::shared_ptr<Human> b, int x)
{
b->setAge(b->getAge()+x);
if(b->getAge()>18 && b->getSex()=="Man") {
return std::make_shared<Man>(b->getAge());
} else if(b->getAge()>18 && b->getSex()=="Woman") {
return std::make_shared<Woman>(b->getAge());
} else {
return b;
}
}
int main(){
std::shared_ptr<Human> x = std::make_shared<Child>;
x = x*19;
}
This doesn't seem like a good design though. A Human's status as a child or adult would be better represented as an attribute of the object or by a function that checks if age is greater than 18.
You cannot make the type T<Derived> inherit from T<Base> because C++ templates do not support covariance. To do so would be unsafe for certain types, such as mutable references to containers. (Imagine taking a reference to std::vector<Cat> as std::vector<Animal>& and pushing back a dog!)
(I would make this answer a comment, but I don't have comment abilities.)
Update:
You can write a non-template wrapper that handles heap data:
class Wrapper
{
public:
Wrapper(Base* b) : raw(b) {}
~Wrapper() { delete raw; }
Base& get() { return *base; }
private:
Base* raw;
}
Of course, in your example, you use std::shared_ptr and not std::unique_ptr. You would have to handle reference counting instead of simply deleting the data in the destructor, but the technique of keeping an internal raw pointer still stands.
Update 2:
The above code could be used as is to provide a level of indirection, such that all classes that inherit from the base class may be held in the same type, without writing your own reference counter:
std::shared_ptr<Wrapper>
This solution may be seen as similar to doing std::shared_ptr<Base*>, except that the latter solution would leak memory.
I am a novice C++ programmer who is currently a student at my local University. I am doing this assignment and I am told to create a linked list of a class called Car, to create a "train". I have two derived classes which simply print differently.
What I want to do is create a list of train cars, and have two pointers pointing to the current Car of each type (Chair and Sleeping) so I know when the user wants to book a seat of a certain type within the train, I know exactly where to go there. When a train is full, the plan is to put a new train of that type onto the end. Ex: Sleeping Car's last seat is booked, a new Sleeping Car will be created and put at the end of the train. The current Sleeping Car pointer will now point to the new Car at the end of the list.
Below is the code I have for this program:
carTest.cc
int main()
{
int trainId = 0;
list<Car> train;
// Testing Car Default Constructor
// Testing Car Constructor
//cout << "Creating a \"Chair car\"... " << endl;
Car* currChair = nullptr, *currSleep = nullptr;
train.push_back(ChairCar(trainId++));
currChair = &train.back();
train.push_back(SleepingCar(trainId++));
currSleep = &train.back();
// Testing bookSeat
//book_seat_test(car2);
// Testing isTypeAvailable
//is_type_available_test(car2);
// Testing isBooked
//is_booked_test(car2);
// Testing mostAvailable
//most_available_test(car2);
// Testing firstAvailable
//first_available_test(car2);
// Testing getSeatNumber
///get_seat_number_test(car2);
// Testing getIndex
//get_index_test(car2);
// Testing bookFirstAvailable
//book_first_available_test(car2);
// Testing chairCar printStatus
//chairCar_print_status_test(*currChair);
// Testing sleepingCar printStatus
//sleepingCar_print_status_test(*currSleep);
currSleep = nullptr;
currChair = nullptr;
return 0;
}
car.h
class Car
{
public:
class Seat
{
public:
Seat() : row(-1), col(-1) {};
Seat(int i, int j) : row(i), col(j) {};
int getRow() const { return row; }
int getCol() const { return col; }
private:
int row;
int col;
};
public:
// Contructors
Car();
explicit Car(int, int, int);
// Deconstructor
~Car();
// Public Member Functions
bool bookSeat(int, int);
bool isTypeAvailable(int) const;
bool isBooked() const;
int mostAvailable() const;
int firstAvailable(int) const;
int getSeatNumber(int, int) const;
Seat getIndex(int) const;
int bookFirstAvailable(int);
virtual void printStatus(int) const;
protected:
int carNumber;
int rows;
int cols;
bool** plan;
int* numAvailable;
int columnSeperation;
void init();
};
car.cc
// function: Deconstructor
// Description:
// The Deconstructor simply frees the dynamically allocated memory
// of the data members plan and numAvailable if the members are not pointing
// to the nullptr.
Car::~Car()
{
if(plan != nullptr)
{
delete[] plan;
plan = nullptr;
}
if(numAvailable != nullptr)
{
delete[] numAvailable;
numAvailable = nullptr;
}
}
chairCar.h
class ChairCar : public Car
{
public:
ChairCar();
ChairCar(int);
protected:
void printStatus(int seatNumber) const;
};
#endif
chairCar.cc
#include "chairCar.h"
ChairCar::ChairCar()
: Car()
{
}
ChairCar::ChairCar(int id)
: Car(7,4,id)
{
}
void ChairCar::printStatus(int seatNumber) const
{
int maxSeatNumber = (rows-1)*cols+(cols-1);
if(seatNumber > maxSeatNumber || seatNumber < 0)
throw OutOfRangeException(seatNumber, 0, maxSeatNumber);
cout << setw(columnSeperation) << ' ' << " |";
cout << setw(columnSeperation) << "WL";
cout << setw(columnSeperation) << "ML";
cout << setw(columnSeperation) << "MR";
cout << setw(columnSeperation) << "WR";
cout << endl;
Car::printStatus(seatNumber);
}
Sleeping Car is exactly the same as Chair Car except different arguments are sent to the base constructor. When I run the code in the main function I get
Error in
`/home/w1llbedone/Programming/cpsc2620/assn/a4/carTest': double free or corruption (fasttop): 0x0000000000608010
I was trying to set the currCar pointers to nullptr before end of the scope to avoid this error. Can anyone explain to me why this happens? This is my first time posting on StackExchange, so I apologise for any lack of information. Any help would be greatly appreciated.
There are at least two major bugs in the partially-shown code. Bug #1:
list<Car> train;
// ...
train.push_back(ChairCar(trainId++));
This is a textbook case of object slicing. train is a std::list of Cars. The shown code constructs a ChairCar, and puts it into the list. This slices off the ChairCar subclass, and copies the Car superclass into the list.
Bug #2 is the primary bug here: this class violates the Rule Of Three. Car's destructor clearly deletes class members that were constructed in dynamic scope. However, the Car class does not define a copy constructor, nor the assignment operator. This pretty much rules out the chances of this class being Rule-of-three compliant.
So, these two bugs result in a lethal combination. During the initial object slicing, the temporary ChairCar object gets destroyed, but only after a copy of its Car superclass gets copy-constructed into the list's container. As part of the destruction, Car's destructor deletes its dynamically-scoped class members.
Then, eventually, the list container gets destroyed, and the sliced off Car, in the list, gets destroyed, and its destructor attempts to delete the pointers that were already deleted.
Game over.
First of all sorry if i've chosen wrong title, but wasn't sure how to name it.
Code structure first:
//== 1st file ==
class A {
private:
int x;
public:
int GetX() { return x; }
};
//== 2nd file ==
class B {
private:
A ob1;
public:
virtual A & GetARef() { return ob1; }
};
class C : public B {
private:
A ob2;
public:
A & GetARef() { return ob2; }
};
class D : public B {
public:
// something else w/e
};
//== 3rd file ==
class E {
private:
std::map <int,C> m;
public:
C* GetCPtr(int idx) { return &m[idx]; }
};
//== 4th file ==
void foo(E & E_Obj) {
std::vector <B*> v;
v.push_back(E_Obj.GetCPtr(0));
v.push_back(/*some pointer to D class*/);
Boo(v); // FORGOT TO ADD IT ! Sorry
};
//== 5th file ==
void Boo(std::vector <B*> & v) {
std::cout << v[0]->GetARef().GetX(); // returns B::ob1 's x instead of C::ob2 's x.
};
As wrote in comments, Boo gets wrong 'x'. I just wonder if it's because that pointers go 'out of scope' or I misdesigned something wrong. How to fix that, so I can get proper x (C::ob2 's one).
Sorry for kinda strange class names etc., but orginal code is much longer, so I tried to show the situation only.
#edit
Forgot to add that in Foo() it returns what i expect - C::ob2 's x.
This is the essence of what you are doing
#include <iostream>
using namespace std;
class Base{
const int b = 0;
public:
virtual const int& getInt(){
return b;
}
};
class LeafOverriding : public Base{
const int l = 1;
public:
virtual const int& getInt(){
return l;
}
};
class Leaf : public Base{
};
int main(){
cout << Leaf().getInt() << '\t' << LeafOverriding().getInt() << endl;
}
and it has no problems (i.e. it does indeed output 0 1). I would say that your snippet -- which does not compile, btw -- does not represent the real code.
I'm so lazy I forced you to compile it with C++11 support, because of const int b = 0 and const int l = 1 :)
Sorry for not leaving reply in comments, but I decided it's worth whole post. Also sorry for such late reply. I've spent whole day and night digging slowly through code, since you've proved that my coding was fine (except few typos in example code, sorry for that). Practically after rewriting code letter after letter I finally found the troublemaker somewhere I would normally never look for. My co-worker while sorting some things was switching not the pointers in related vector but their content.
Something like that
vector <E*> v;
// ...
*v[i] = ...
instead of
v[i] = ...
After fixing that, it indeed works as intented. Thanks for your help and clearing things out. Also sorry for wasting your time.