SNAP FAQ


Q: The given insertion operator overloading function causes my code to fail to compile!

This is a common mistake that brings up a great conversation: const functions and objects. When a function is declared as const it is a guarantee that the function call will not change any of the data members (or state) of that object. By extension, it is also not allowed to call any non-const functions because they may change the data members of the object. That is why it is best to be consistent with your function qualifiers. Any function that does not change the state of the object should be qualified as const, which is a consistent criteria for the peer-review sections of all the labs

Now that we understand what a const function is, let's discuss const objects. When an object is declared as const, its data members (state) cannot be changed after its assignment. This means that no non-const function can be called on a const object. Look at the given code and try to see if you can find your mistake:

string toString() const {
	stringstream out;
	out << "Name = " << getName();
	return out.str();
}

friend std::ostream& operator<< (ostream& os, const MyClass& myclass) {
	os << myclass.toString();
	return os;
}
					
Note that in order for the toString() call to respect the const qualifier on the myclass object, it can only call const functions on it. If you forget to make your toString() function const, it will fail to compile.

Q: What is an exception? How do I throw an exception?

An exception could be a lot of different things. Some common exceptions you have probably seen in your code might be an out_of_range exception that was caused by you going outside of the bounds of some data structure, like an array or a vector. When you do something that the compiler doesn't like, it will throw an exception related to your error and your program will crash if it is not handled.

You can actually throw your own exceptions if you want. Now how is this useful? If you are reading in an input file and you are looking for certain input then, if you get erroneous input, you could throw an exception that gets caught and outputs whatever you want to.

For example:
Let's say that the I'm reading in input to some string variable called line. I check to see the contents of this variable and if it is incorrect I want to output that line, but I want to throw some kind of exception.

if(line != "Correct input") {
   throw string(line);
}

Essentially what you are doing here is throwing a new string variable that is filled with whatever the contents of line contained.
You could also throw any number of exceptions such as throw out_of_range("SOME STRING")

We will go over what happens to the thing you threw in the next FAQ, but hopefully you can see what happens when things are thrown and when you might want to throw stuff in your own code.

Q: How can I use a try-catch block to handle exceptions?

A try-catch block is put around code that you think might throw an exception, or in the case of this project it's placed around code that you know will throw an exception because you told it to with a throw statement.

Let's say you have some block of code with a bunch of if statements in it, and you put all of it in a try-catch block:

try {
   if(//STATEMENT 1) {}
   if(//STATEMENT 2) {}
   ...
   if(line != "Correct input") {
      throw string(line);
   }
} catch(string errorString) {
  cout << "ERROR: " << errorString << endl;
}

What you are saying to the compiler is try and do all of this code, and if any of these lines cause an error where a string is thrown, do whatever is said inside of the catch statement instead of crashing the program.

In this example, when throw string(line); is called, it throws a string variable that has the contents of line in it. Then it is caught by the catch statement and some new variable which we called errorString is now filled with what we threw, which ends up being whatever line contained. Lastly we output the line, but we precede it with our own output, in this case being "ERROR: ".
So if out original "line" variable contained the string "This isn't correct", our above code would output:

ERROR: This isn't correct

Try-catch blocks can be very useful for a number of things. Maybe you are doing a for loop over an array, and if you go out of bounds you want to just throw an "out_of_range" exception and keep going with your program. When a throw statement is called, it will skip over all the code below it until it gets to the catch, and the continue on if there is code after the catch statement. This is super nice if you have exceptions that you want to handle, and not end your program. Try experimenting with different throwables to get a better grasp on how this works!

How do I do make a class inherit from 2 different classes?

You might have an instance where you want a single class to be the child of 2 different parent classes. To do this make sure that you #include both of the .h files for the two parent classes, and then declare the child class like this.

class ChildClass : public ParentOne, public ParentTwo {
	//CLASS DETAILS IN HERE
};