My teacher asked the class to fix the error in this program. Actually it seems to be a crappy program; I just typed it exactly how it is in the sheet, and got this error:
Well Now I have just change some things, but get this exception at run time: Microsoft C++ exception: [rethrow] at memory location 0x00000000..
The code is now like so: (The variable an class names are now in spanish, sorry for the inconviniences)
#include <iostream>
#include <exception>
#include <stack>
using namespace std;
class EPilaVacia : public exception{
public:
const char* what() const throw(){
return "Error: Pila Vacía";
}
};
template <class T, int max=100>
class Pila{
private:
stack<T*> *pila;
int cont;
public:
Pila() : cont(0){
pila=new stack<T*>();
}
virtual void apilar( T* pt){
if(cont<max){
pila->push(pt); //respuesta 2
}
}
virtual void apilar(T t){
if(cont<max){
pila->push(&t); //respuesta 3
}
}
T tope() const throw (EPilaVacia){
if(cont>0){
pila->top(); //respuesta 4
}else{
throw ; //respuesta 5
}
}
T& desapilar() throw (EPilaVacia){
if(cont>0){
pila->pop(); //respuesta 6
}else{
throw ; //respuesta 7
}
}
int size() const{
return pila->size();
}
};
class Figura{
public:
virtual void print(){
cout<< "FIGURA" <<endl;
}
};
class Circulo : public Figura{
public:
void print(){
cout<<"CIRCULO"<<endl;
}
};
class Triangulo : public Figura{
public:
void print(){
cout<<"TRIANGULO"<<endl;
}
};
int main(){
Pila<Figura*> *pfiguras= new Pila<Figura*>();
pfiguras->apilar(new Circulo());
pfiguras->apilar(new Triangulo());
Pila<Figura*> pfiguras2(*pfiguras);
pfiguras->tope()->print();
pfiguras->desapilar();
pfiguras->tope()->print();
pfiguras->desapilar();
pfiguras2.tope()->print();
system("Pause");
return 0;
}
Where to start? This has a lot of errors.
Don't have "using namespace std;", it clutters the global namespace. Rather, use std::list, std::cin, etc. using the namespace to identify the specific object or class.
In the exception class, don't write your own what() method. Just initialise the base class in the constructor.
class EPilaVacia : public std::exception
{
public:
EPilaVacia()
: std::exception("Error: Pila Vacía")
{
}
};
I assume that the class Pila is just a learning exercise. In real life you would use std::stack, not make your own.
If you are implementing the stack with a list, you don't need a "max" parameter.
Don't allocate the list dynamically, that is silly. Just use
std::list<T*> ila;
You don't need "cont". Use ila.size();
Don't make the functions like apilar() virtual. The list is private, so subclasses cannot access it, thus the methods cannot be overriden. Also, you don't have a virtual destructor, so inheritance is probably a bad idea.
void apilar(T t) is a disaster. You pass t by value, then store the address of the parameter, which then goes out of scope. The function is unnecessary, lose it.
Don't put "throw (EPilaVacia)" in method declarations. No compiler implements it and it is deprecated in the new C++11 standard.
In tope(), use ila.back(), not ila.pop_back().
T tope() const
{
if(ila.empty())
{
throw EPilaVacia();
}
else
{
return *ila.back();
}
}
In desapilar(), don't use clear as it will empty out the stack. Use something like this
T& desapilar()
{
if(ila.empty())
{
throw EPilaVacia();
}
else
{
T *pt = ila.back();
ila.pop_back();
return *pt;
}
}
NEVER use system("Pause"); Use std::cin.get();
The objects you allocate with new are never deleted. You have a memory leak.
There are probably more, but that should get you started.
Note: I've scrawled this down quickly. There are probably errors above, so check my code, don't just copy it.
Is this error happening on line "mystack=new stack<T>;" as that's the only line I see that might cause this. The reason for that is that mystack is defined as T*, not stack<T>. When the compiler tries to assign the new stack<T> to mystack, it sees that mystack is looking for T*, and says "I don't know how to make stack<T> into T*".
Now that you've fixed that error, you are getting a throw from nullptr exception. This would be best solved, normally, by running this under a debugger and seeing what line causes your program to behave poorly. However, by inspection, it appears that you're only pushing two things onto the stack, then try to use "top" to get a third: pfiguras2.tope()->print();.
You're also leaking memory, but Michael J's comment goes much better into the more nitpicky, less "make it not crash" area of this code.
Related
I'm trying to create a constructor in which the strings are dynamically allocated. I've looked up dynamically allocated memory several times and watched a video about it, but I'm still not 100% sure if I'm understanding the concept. I'm hoping an example specific to what I'm coding will help me out a bit.
These are the private variables I have in my h file:
string* tableID;
int numSeats;
string* serverName;
With that in mind, could someone tell me how I could dynamically allocate memory for the strings in this constructor?
Table::Table(const string& tableID, int numSeats, const string& serverName) {
}
Finally, I would greatly appreciate it if someone could tell me the purpose of dynamically allocated memory. I've see explanations on what dynamically allocate memory is, but I'm not understanding the use of it. Why use dynamically allocated memory? What are the benefits? What are the drawbacks? Thank you!
EDIT: I'm including the rest of the h file. Note that this wasn't created by me, so I can't make changes to it. I can only adhere to it in the cpp file.
#include <string>
#include "party.h"
using std::string;
class Table {
public:
Table();
Table(const string& tableID, int numSeats, const string& serverName);
~Table();
const string* getTableID() const { return tableID; }
int getNumSeats() const { return numSeats; }
const string* getServerName() const { return serverName; }
void decrementTimer() { timer--; }
int getTimer() const { return timer; }
void setTimer(int duration) { timer = duration; }
const Party* getParty() { return party; }
void seatParty(const Party* newParty);
void clearTable() { party = nullptr; timer = 0; }
private:
string* tableID;
int numSeats;
string* serverName;
int timer;
const Party* party;
};
The easiest way to get what you want is to take advantage of the Member Initializer List as this also solves the problem of having the parameters shadow the member variables of the same name.
Table::Table(const string& tableID,
int numSeats,
const string& serverName):
tableID(new string(tableID)),
numSeats(numSeats),
serverName(new string(serverName))
{
}
Allocation is performed with the new operator. Later you will have to release the dynamically allocated memory with the delete operator. Here is documentation on new and the same for delete.
But the use a pointer requirement is bizarre as storing pointers to string makes everything else you with the class do orders of magnitude more difficult. This may be the point of the assignment, but there are better and less-confusing ways to teach this lesson.
The allocated strings must be released. The C++ idiom of Resource Allocation Is Initialization (What is meant by Resource Acquisition is Initialization (RAII)?) suggests you have a destructor to automate clean-up to ensure that it is done. If you need a destructor, you almost always need the other two members of The Big Three (What is The Rule of Three?) and possibly need to take The Rule of Five into account as well.
Whereas because string observes the Rule of Five for you, you should be able to take advantage of the Rule of Zero and implement no special functions.
M.M raises an excellent point in the comments. The above example is too naive. It is probably all you need for the assignment, but it's not good enough for real code. Sooner or later it will fail. Example of how it fails.
First we replace string with something that can expose the error:
class throwsecond
{
static int count;
public:
throwsecond(const string &)
{
if (count ++)
{
count = 0; // reset count so only every second fails
throw runtime_error("Kaboom!");
}
cout << "Constructed\n";
}
~throwsecond()
{
cout << "Destructed\n";
}
};
int throwsecond::count = 0;
Then a simple class that does basically the above with less frills
class bad_example
{
throwsecond * a;
throwsecond * b;
public:
bad_example(): a(nullptr), b(nullptr)
{
}
bad_example (const string& a,
const string& b)
{
this->a = new throwsecond(a);
this->b = new throwsecond(b);
}
~bad_example()
{
delete a;
delete b;
}
};
and a main to exercise it
int main()
{
cout << "Bad example\n";
try
{
bad_example("", "");
}
catch (...)
{
cout << "Caught exception\n";
}
}
Output:
Bad example
Constructed
Caught exception
We have an object constructed and never destroyed.
Since a default constructor has been defined by Table we can, with a compiler that supports the C++11 or a more recent Standard, take advantage of delegated constructors to force destruction of the partially constructed object because it has been fully constructed by the default constructor.
class good_example
{
throwsecond * a;
throwsecond * b;
public:
good_example():
a(nullptr), b(nullptr) //must be nulled or destruction is dicey
{
}
good_example (const string& a,
const string& b) : good_example() // call default constructor
{
this->a = new throwsecond(a);
this->b = new throwsecond(b);
}
~good_example()
{
delete a;
delete b;
}
};
Output:
Good example
Constructed
Destructed
Caught exception
One construct and one destruct. The beauty of this approach is it scales well and adds nothing to the code that you don't already have. The cost is minimal, a and b get initialized and then assigned as opposed to just initialization. Faster code is useless if it doesn't work.
Full example: https://ideone.com/0ckSge
If you can't compile to a modern standard, you wind up doing something like
the next snippet to make sure everything is deleted. It's main sin is it's ugly, but as you add more classes that must be constructed and destroyed it starts getting unwieldy.
Table::Table(const string& tableID,
int numSeats,
const string& serverName):
tableID(NULL),
numSeats(numSeats),
serverName(NULL)
{
try
{
this->tableID(new string(tableID)),
// see all the this->es? don't shadow variables and you won't have this problem
// miss a this-> and you'll have a really bad day of debugging
this->serverName(new string(serverName))
// more here as required
}
catch (...)
{
delete this->tableID;
delete this->serverName;
// more here as required
throw;
}
}
There is probably a way to improve on this and make it more manageable, but I don't know it. I just use newer standards and value semantics (I'd love it if someone can provide a good link that describes this concept) where possible.
I am a noob working on my very basic hobby program on chemestry, where i have created a class compound and added string compundname, but i want to design it in such a way that when i put in some invalid element in compund string, ex- NaMmO4 the compiler will not let me create object and instead come with an error something like "Mm invalid element"
Note:: my concern here is only with error handling.
example
compound sodiumsalt {"NMmO4"}
compiler should give error something like -
Mm is an Invalid element. cannot create object.
You are confused about the job of the compiler and what compiler-errors are.
Compiler errors are mostly sintax error and easy-to-spot running errors, where the compiler doesn't know what are you trying to do. To write the wrong string name will never be a compiler error. Also, it seems the name will be written at running time, which happens after compiler-time.
Might want to do something like this:
#include <iostream>
#include <exception>
using namespace std;
//some people are heavily against it, but I think is easier to use it if you are a beginner.
enum class elem_t{elem1, elem2, elem3};
class outOfBound: public exception
{
virtual const char* what() const throw()
{
return "Error: Accessed an element that doesn't exists.";
}
} noElem;
class Compound{
public:
Compound(elem_t* elems, int size){_elems = elems; _size = size;}
//can't include something is not part of elem_t
elem_t operator()(unsigned pos) const {if(pos < _size) return _elems[pos]; else throw noElem;}
int size() const{return _size;}
private:
elem_t* _elems;
int _size;
};
int main()
{
elem_t a[] = {elem_t::elem2, elem_t::elem1};
Compound first(a,2);
return 0;
}
The only basic thing I didn't do is a print() or operator<<, but it should be easy.
I needed to use some class today that followed this basic design:
class Task {
public:
Task() {
Handler::instance().add(this);
}
virtual void doSomething() = 0;
};
class Handler {
std::vector<Task*> vec;
//yea yea, we are locking the option to use default constructor etc
public:
static Handler& instance() {
static Handler handler;
return handler;
}
void add(Task* task) {
vec.push_back(task);
}
void handle() {
for (auto t : vec) {
t->doSomething();
}
}
};
template <class T, int SIZE>
class MyTask : public Task {
T data[SIZE];
public:
virtual void doSomething() {
// actually do something
}
};
//somewhere in the code:
Handler::instance().handle();
now, my class is something like
class A {
MyTask<bool, 128> myTask;
public:
A(int i) {}
};
the way I wanted to do it is having a map where instances of A are values
static std::map<int, A> map = {
{42, A(1948)},
{88, A(-17)}
};
first to clarify something - this code needs to run on a real time embedded system so I'm not allowed to allocate memory using new for several legacy reasons.
My problem was that the actual objects in the map weren't the ones I explicitly created and so they didn't register in the Handler class (so I didn't get the benefit of the Handler::handle calls).
I tried figuring a nice way to solve this without doing something ugly like first creating an array of A then only point to these objects in the map for example.
I never used move semantics before but I've read little bit about them and thought they can be my solution.
however, after reading this answer (specificaly the very first example) it seemed that I can't really benefit anything from using move semantics.
I tried it anyway (coz why the heck not...) and did something like this instead:
static std::map<int, A> map = {
{42, std::move(A(1948))},
{88, std::move(A(-17))}
};
now for my surprise the copy constructor of MyTask was still called (I put print in it to verify) but for some reason now the handler registration worked well and my instances enjoyed the doSomething() calls.
I tried reading more thoroughly about std::move to understand what exactly happened there but couldn't find the answer.
can anyone explain it? does std::move moves the this pointer somehow? or maybe it just caused the registration to happen correctly somehow and had nothing real to do with the moving attempt
thanks
edit:
to further clarify what I'm asking:
I understand the use of std::move was not contributing to what's being done there.
But for some reason it did get my objects in the map to get the doSomething() calls through the handler. I'm looking for that reason
on a side note as it probably belongs to a different question - is there any decent way to initialize a map this way without the overhead of creating each object twice?
Your question has a lot more in it than it needs to but I think I understand the root question here. The std::map constructor receives an initialization_list, you're calling (5) from this list. Objects are copied out of an initializer_list when iterating over it rather than moved because a copy of an initializer_list doesn't copy the underlying objects. The same affects other std containers, here is an example with vector to demonstrate. (live link)
#include <vector>
#include <iostream>
struct Printer {
Printer() { std::cout << "default ctor\n"; }
Printer(const Printer&) { std::cout << "copy\n"; }
Printer(Printer&&) { std::cout << "move\n"; }
};
int main() {
std::vector<Printer> v = {Printer{}};
}
if you use {std::move(Printer{})} you'll add another move into the mix that the compiler can't easily get optimize away.
I'm trying to make a chess program, but I want to be able to implement different AIs in it. Thus I made a abstract AIgeneric class and the derived class AIrandom off of AIgeneric. Then in my chessAI interface, I create a list of the the AIs, and try to call their getNextMove function and run into a segfault. The code is as below:
class AIgeneric {
public:
virtual int getNextMove(int*, const int &) = 0;
}
class AIrandom : public AIgeneric {
public:
AIrandom();
virtual int getNextMove(int*, const int &);
}
class chessAI {
public:
chessAI();
~chessAI();
void setAI();
int getNextMove(int*, const int &);
private:
vector<AIgeneric*> AIlist;
vector<string> names;
int selectedAI;
};
chessAI::chessAI () {
AIrandom randomAI;
AIlist.push_back(&randomAI);
names.push_back("Random AI");
selectedAI = -1;
}
int chessAI::getNextMove(int * board, const int & color) {
return AIlist[selectedAI]->getNextMove(board, color); //segfault on this line
}
It'd be great if anyone could help me on this problem!
Edit: I do set selectedAI to 0 before calling getNextMove.
In this code:
chessAI::chessAI () {
AIrandom randomAI;
AIlist.push_back(&randomAI);
names.push_back("Random AI");
selectedAI = -1;
}
You store a pointer to a local variable into your vector. After the constructor returns that pointer is no longer valid.
Remember that all local variables are stored on the stack, and the stack is reused in other functions. So when you use the pointer in the vector, it now points to some other functions memory and not the one object you declared.
This can be solved in three ways:
Allocate the object on the heap:
AIlist.push_back(new AIRandom);
Not using pointers at all.
Use smart pointers, such as std::unique_ptr.
You call selectedAI = -1; and then AIlist[selectedAI]->.... What do you expect AIlist[-1] to be, other than undefined behavior?
I expect this is because AIlist[selectedAI] is out of bounds. You can confirm this by replacing it with AIlist.at(selectedAI). Keep in mind that this index is -1 immediately after the constructor...
I'm quite new to C++ and I am trying to store objects inside a std::vector like this:
Event.h:
//event.h
class Event
{
public:
Event();
Event(std::string name);
~Event();
void addVisitor(Visitor visitor);
private:
std::vector<Visitor> m_visitors;
};
Event.cpp:
//event.cpp
Event::Event() :
m_name("Unnamed Event")
{
}
Event::Event(std::string name) :
m_name(name)
{
}
void Event::addVisitor(Visitor visitor)
{
this->m_visitors.push_back(visitor);
}
void Event::listVisitors()
{
std::vector<Visitor>::iterator it;
for(it = this->m_visitors.begin();it != this->m_visitors.end(); ++it)
{
std::cout << it->getName() << std::endl;
}
}
Visitor.h:
//visitor.h
class Visitor
{
public:
Visitor();
Visitor(std::string name);
~Visitor();
std::string getName() const;
void listVisitors();
private:
std::string m_name;
};
Visitor.cpp:
//visitor.cpp
Visitor::Visitor() :
m_name("John Doe")
{
}
Visitor::Visitor(std::string name) :
m_name(name)
{
}
std::string Visitor::getName() const
{
return m_name;
}
main.cpp:
//main.cpp
int main()
{
Event *e1 = new Event("Whatever");
Visitor *v1 = new Visitor("Dummy1");
Visitor *v2 = new Visitor("Dummy2");
e1->addVisitor(*v1);
e1->addVisitor(*v2);
}
If I do it like this I would have to add a copy constructor which would make a deep copy so the object gets copied properly into the vector. I'm looking for a way around it by only storing pointers to the objects in a vector.
I already tried it with std::vector<std::unique_ptr<Visitor> > m_visitors, but then I got some errors when calling addVisitor in main.cpp. Of course I changed the declaration of the class members accordingly.
How would an appropriate declaration of the members and the member function look like to make it work?
Stylistically, if you are passing pointers, just accept pointers as the function arguments.
What's happening in the example code above is that the visitors are getting copied to become function arguments and the pointers you had are unreferenced by anything outside of the main function.
I can't speak to what the errors are that you're seeing as you didn't describe them but it probably has to do with incompatible types.
Just get rid of the news because for these data structures they're unnecessary.
int main()
{
Event e1("Whatever");
Visitor v1("Dummy1");
Visitor v2("Dummy2");
e1.addVisitor(v1);
e1.addVisitor(v2);
}
I would suggest that if you don't know how to use pointers you couldn't possibly want to store them instead (they're a hassle IMO to store in the vector when copying by value works just fine).
The compiler generated copy constructor should work just fine.
No manual deep copy required, because you are quite correctly using std::string, which supports RAII.
However, your main function has three memory leaks — there is no need to use new there anyway, so simply don't.
General rule of thumb:
If, at any time T, you're thinking of introducing more pointers into your code, then you're probably going in the wrong direction.