Catch and Throw Statements within A function - c++

I have a matrixType File that works fine, but I am now trying to replace the if statements with the try, catch, and throw statements within a function of a class. I am just trying to understand one function so I can apply it to the others. Since I did try to do the try and catch statements but it skipped over the try statement and caused an actual exception that stops the program completely.
The One function I am focusing on is the equal operator
Here is the HeaderFile
#pragma once
#include
#include
#include
#include
#include
#include
using namespace std;
class matrixType
{
private:
int **matrix;
int row;
int col;
public:
const matrixType& operator=(const matrixType& mat);
}
Here is the class.cpp file that currently works
#include "matrixType.h"
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <stdexcept>
#include <limits>
using namespace std;
const matrixType& matrixType::operator=(const matrixType& mat)
{
if (row != mat.row || col != mat.col)
{
cout << "The matrixes are not identical" << endl;
return *this;
}
for (int i = 0; i < row; i++)
{
for (int r = 0; r < col; r++)
{
matrix[i][r] = mat.matrix[i][r];
}
}
return *this;
}
Then this is the source file
#include <iostream>
#include <string>
#include <stdexcept>
#include <limits>
#include "matrixType.h"
using namespace std;
int main()
{
matrixType test1(3, 3);
matrixType test2(2, 2);
test1 = test2;
return 0;
}
So the big question is how do you throw an exception
I tried
Try
{
if(mat.row != row || mat.col != col)
throw exception("The matrixes are not identical")
}
catch (exception & e)
{
cout << e.what << endl;
}
Which caused the actual exception to pop up but when I leave the if statement it works and does not go into a fail state. Does anyone see what I was doing wrong if I replaced the if statement with the code above?

First, a note about the meaning of exceptions. Further down, I'll address what's wrong with your code.
The meaning of throwing an exception in C++, in English, is roughly, "I can't deal with this situation anymore, I'm giving up right now, and I'm hoping that somebody else can deal with this." The meaning of catching an exception is roughly, "oops, somebody screwed up, but I'm going to do something about it now." With this in mind, let's look at how this works in more concrete detail.
Many functions have preconditions, which are things that function always expects to be true before it runs. For example, a squareRoot(double x) function might have a precondition that x must never be negative. When a function's precondition is violated, it's a natural time for that function to say "I'm giving up right now, deal with it!" since somebody who called that function is doing something wrong, and squareRoot can't possibly fix that. This could look like the following:
// precondition: x must not be negative
double squareRoot(double x){
if (x < 0.0){
// precondition is violated
throw std::runtime_error("input to squareRoot was negative");
// the function exits here!
// this point in code is not reachable
}
// otherwise, precondition is satisfied, it's safe to continue
...
return result;
}
elsewhere, in the wild:
void myFunction(){
double x;
cout << "x = ";
cin >> x;
double y = squareRoot(x);
cout << ", y = " << y << '\n';
}
Here, if somebody types in a negative number, then the preconditions of squareRoot are violated, and it throws an exception. This means that squareRoot will not return normally, and neither will myFunction. When exception is thrown, everything is interrupted until you catch the exception, which can happen far outside the current function.
int main(){
try {
myFunction(); // this might throw
// if myFunction() throws, the following output will not happen!
cout << "Thanks! have a nice day.\n";
} catch (std::runtime_error e) {
// if myFunction() does throw, the error lands right here
cout << "Oops! an error occurred: " << e.what() << '\n';
}
return 0;
}
It's important to note that you should only throw exceptions when something is really wrong. Exceptions are not a replacement for ordinary program logic, and they're not a replacement for validating things like user input.
About custom classes:
When you're defining a custom class type, if it has either a copy constructor, copy assignment operator, or destructor, that probably means that your class has sensitive information that needs special care to clean up and keep track of. If you've written at least one of these functions, you should implement all three of them. Otherwise, it's extremely easy to introduce memory leaks, false data sharing, and all kinds of unwanted Undefined Behavior into your program.
About your copy assignment operator:
The purpose of a copy assignment operator, as in a = b; is that after it runs, the left-hand object should be logically identical to the right-hand object, and the right-hand object should not have changed. The previous state of the left-hand object is lost at this point. What exactly logically identical means is a question of what your class is representing.
In the case a simple matrix, I would expect two matrices to be identical when they have the same width, height, and values for all elements, and I would implement a copy assignment operator accordingly. For example:
Matrix& Matrix::operator=(const Matrix& other){
releaseMemory(); // clean up old data
resize(other.rows, other.cols); // allocate new data
for (int i = 0; i < rows; ++i){
for (int j = 0; j < cols; ++j){
this->data[i][j] = other.data[i][j]; // copy each value
}
}
return *this;
}
I leave the implementation of the details to you. You should be able to find great examples and detailed explanations of how to overload operators, write your own copy constructor and destructor, and about good practice in general by reading a good C++ book.

Actually, I figured it out I have to use return statements as it worked when I included a return statement within the catch function.

Related

Constructor not getting called

I am making an array of 4 std::list. But when I try to access the array's first list's first A object and call the callMe() method on it I get a weird output.
Now 2 things could have happened:
Either the list was empty.
An A object was created when I tried to access the first element of the first list((*(arrayOflistOfA[0].begin()))).
Details of the above cases:
If no A object was created then I should have got an exception. But I didn't get any exception so I am assuming that an A object was created.
So if an A object was indeed created, then the constructor should have been called.
What am I missing?
#include <iostream>
using namespace std;
class A {
public:
A() {
cout<<"Constructor called"<<endl;
x=20;
}
void callMe();
private:
int x;
};
void A::callMe() {
cout<<"Value of x = "<<x<<endl;
}
int main() {
const int size = 4;
list<A>* arrayOflistOfA = new list<A>[size];
(*(arrayOflistOfA[0].begin())).callMe();
}
The output is:
Value of x = 0
but the output should have been:
Constructor called
Value of x = 20
If no A object was created then I should have got an exception.
Not true.
But I didn't get any exception so I am assuming that an A object was created.
Don't assume. Find out. Go to some documentation for begin() and for iterators and discover that you do not get an exception, you get UB.
An A object was created when I tried to access the first element of the first list((*(arrayOflistOfA[0].begin()))). [And] if an A object was indeed created, then the constructor should have been called.
That's right. Clearly you have no elements in the list.
And we know that, because there is no code in your program that adds elements to the list.
Also you should not dynamically allocate containers unless you really, really need to (I've never found a need to).
You aren't actually populating the list with any values. I tested the below code and include a commented explanation.
#include <iostream>
#include <list>
using namespace std;
class A {
public:
A();
void callMe();
private:
int x = 0;
};
A::A()
{
cout << "Constructor called" << endl;
x = 20;
}
void A::callMe() {
cout << "Value of x = " << x << endl;
}
int main() {
const int size = 4;
list<A>* arrayOflistOfA = new list<A>[size];
cout << arrayOflistOfA->size() << endl; // As you can see, size is 0 here - you created a list of nulls.
for (int i = 0; i < size; i++)
{
arrayOflistOfA->push_back(A());
}
// The below code demonstrates how to loop through the array once it's populated.
list<A>::iterator it;
for (auto& a : *arrayOflistOfA)
{
a.callMe();
}
return 0;
}
I got the answer to my question. Firstly I tried to run this code on my mac with GNU C++ compiler but when I ran the same code on an iPhone simulator it crashed. So as #PaulMcKenzie mentioned, I was indeed trying to dereference an invalid iterator.

Pretty confused about C++ Exception Handling

Trying to add exception handling to my C++ program, but I find it pretty confusing. The program sets the values i and j to their highest possible values and increments them. I think I want the exception handling to detect the integer overflow / wraparound when it happens(?)
So far this is what I've got:
#include <iostream>
#include <limits.h>
#include <exception>
#include <stdexcept>
using namespace std;
int main() {
int i;
unsigned int j;
try{
i = INT_MAX;
i++;
cout<<i;
}
catch( const std::exception& e){
cout<<"Exception Error!";
}
try{
j = UINT_MAX;
j++;
cout<<j;
}
catch(const std::exception& e){
cout<<"Exception Error!";
}
}
The program runs, but the exception handling part doesn't work.
What could be the issue?
Well the behaviour of incrementing i beyond INT_MAX is undefined. That's because it's a signed integral type. I've never come across an implementation that throws an exception in this case. (Typical behaviour is wrap-around to INT_MIN but don't rely on that.)
Incrementing j beyond UINT_MAX must wrap-around to 0. That's because it's an unsigned type. That is, an exception must never be thrown.
C++ does not define any exceptions to be thrown in case of integer overflow. If you want to achive such behavior you will need some wrapper for integer class with corresponding functionality, such as Safe Int library. Example:
#include <safeint.h>
#include <iostream>
int main()
{
try
{
::msl::utilities::SafeInt<int> j;
for(;;)
{
++j;
}
}
catch(::msl::utilities::SafeIntException const & exception)
{
switch(exception.m_code)
{
case ::msl::utilities::SafeIntArithmeticOverflow:
{
::std::cout << "overflow detected" << ::std::endl;
break;
}
default:
{
break;
}
}
}
return(0);
}
In C++, exceptions don’t just happen. Exceptions are thrown by the throw keyword; if your code (or code you’ve linked to) doesn’t have throw something() it doesn’t throw exceptions.
That’s not quite true, however: there are funky situations where the code does something inappropriate (formally, the code has undefined behavior), which might result in an exception being thrown. That’s outside the rules of the language definition, so not portable and not reliable (yes, I’m looking at you, Windows SEH).

How does C++ treat assignments in try catch blocks?

I use the clang analyzer to check my C++ code for bugs and errors. I have the following construct:
#include <cstdlib>
#include <iostream>
double
somethingThatMayThrow() throw (std::exception)
{
if( rand() % 2 ) {
throw std::exception();
}
return 5.0;
}
int
main()
{
double value = 2.0;
try {
value = somethingThatMayThrow();
} catch( const std::exception& ) {
std::cout << "oops" << std::endl;
}
double someOtherValue = value + 1.0;
std::cout << someOtherValue << std::endl;
return 0;
}
The analyzer now complains that the initial value of variable value is never read. However, it is clear that the value is used in the last line if and only if there is an exception in the try block. Is this understanding correct, and am I looking at a bug in the analyzer? Or am I missing something here?
How does the standard define this behavior? What happens to the left hand side of the assignment if the right hand side throws?
The screenshot below shows the actual code that the analyzer complained about, which has the same structure as my example above:
The analyser is wrong. You are right.
The analyser could be right if the code inside the try block can never throw std::exceptions or objects of a type derived from it (e.g. with noexcept, or with only objects of other types being thrown).
Either way, your interpretation is correct: the assignment will never occur if evaluation of the value-to-be throws. As such, the original value will remain intact.
The compiler sees that you are assigning someValue in the initialization of value but then, inside the try block, you are reassigning it.
And the analyzer is right in the case in which no exception is thrown, but not in the opposite case, where value will still be the same as original someValue.

how does the structure dereference operator work?

I am a java programmer trying to teach myself c++. Please cut me a little slack if I ask simple questions at first.
I would like to understand how the structure dereference operator works. Specifically, can anyone tell me what the following line of code does in explicit terms?
if (elements[i]->test(arga, argb)) {}
test(arga,argb) is a Boolean function in the same class, and elements is a vector of instances of the element class. Here is the code that immediately surrounds the line above, about which I am interested:
for (unsigned i = 0; i < elements.size(); ++i) {
T arga = INFINITY, argb = INFINITY;
//using namespace std;
//std::cout >> elements[i] >> std::endl;
//std::cout >> test(arga, argb) >> std::endl;
if (elements[i]->test(arga, argb)) {
//some code
}
}
It seems that the if line is testing to see whether or not the boolean returned by test(arga,argb) is part of the given instance of the elements class. But when I try to expose the underlying values of elements[i] or test(arga,argb) with the cout lines above, the compiler throws errors until I comment those lines out. In java, I would be able to fiddle around with this until I found values of each that correspond with each other, and then I would understand the line of code. But I do not know how to figure out what this line of code does in C++. Can anyone give me a clear explanation, preferably supported by a link or two to some references online?
elements[i]->test (arga, argb)
If we break down the statement, reading from left-to-right, we will end up with the below:
access the ith element in an array (or array-like) entity named elements
the element accessed (elements[i]) is a pointer to an object
call the member-function named test on elements[i] and pass it two arguments; arga and argb
if we disregard the fact that you wrote std::cout >> instead of std::cout << (the latter is the correct form), we end up with two reasons for your described errors:
your compiler complains about std::cout << element[i] because no suitable overload is found to handle an entity of the type of element[i] and an std::ostream& (which is the underlying type of std::cout).
your compiler complains about std::cout << test (arga, argb) because there is no function in scope named test that takes two arguments corresponding to arga, argv. test, in your snippet, is a member-function that belongs to an entity, it's not callable by its own.
Welcome to C++.
First, the syntax for output is:
cout<<
instead of
cout>>
You are right in guessing that test is a function that returns boolean.Here elements[i] is a pointer pointing to a struct element which has this test function.
To learn C++, you can use these articles that I wrote.Good luck!
Since numerous respondents told me that I need to provide the code before they can answer, I looked deeper in the code, and re-wrote something which tells me that the line:
if (elements[i]->test(arga, argb)) {}
is a test to see whether or not the boolean member function of elements[i] is true.
The c++ program that I wrote to identify the meaning of -> in this context is:
#include "stdafx.h"
#include <vector>
#include <string>
#include <iostream>
template<typename T>
class Bone
{
public:
std::string myName;
int mySize;
Bone(const std::string &name, const int &size) : myName(name), mySize(size)
{}
bool isBigger(const int &testSize) const
{
if (testSize > mySize) return false;
else return true;
}
};
int main(int argc, char **argv)
{
std::vector<Bone<float> *> bones;
// name, location, size
bones.push_back(new Bone<float>("femur", 10));
bones.push_back(new Bone<float>("ulna", 4));
bones.push_back(new Bone<float>("maxilla", 3));
int testSize = 6;
// test each bone to see if it is bigger than testSize
for (unsigned i = 0; i < bones.size(); ++i) {
if (bones[i]->isBigger(testSize)) {
std::cout << bones[i]->myName; std::cout << " is bigger than testSize! " << std::endl;
}
}
while (!bones.empty()) {
Bone<float> *thisBone = bones.back();
bones.pop_back();
delete thisBone;
}
return 0;
}
Thank you to everyone who led me to figure this out.

Vector and []-operator overloading

I have inherited my class from std::vector. Now I want to overload the []-operator.
When I try to assign a new value to my vector, e.g. v[0]=5, I should receive the message OK.
This is my code (I know, that makes no sense, I'm just playing around):
#include<vector>
#include<iostream>
class Vec : public std::vector<int> {
public:
int operator[](int);
};
int Vec::operator[](int i) {
(*this)[i] = i;
std::cout << "OK";
return 123;
}
int main() {
Vec v;
v[0]=5;
}
Unfortunately I get the following error:
In member function ‘int Vec::operator[](int)’:
error: lvalue required as left operand of assignmen
In function ‘int main()’:
error: lvalue required as left operand of assignment
This particular error is caused because you are not returning an lvalue, generally defined as something that can appear to the left of an assignment, such as v[0] = 5;. You have more problems as pointed out in the other answers but this is the specific issue you face with that error message (a).
The correct specification for overloading the index operator is:
int& operator[] (const int nIndex);
You have to return a reference to the item (so it can be modified) if you want to treat it as an lvalue. The following code shows a fix, although obviously all array indexes map to the same value in this simplified case:
#include <vector>
#include <iostream>
class Vec : public std::vector<int> {
public:
int& operator[] (int); // <-- note the '&'
private:
int xyzzy;
};
int& Vec::operator[] (int idx) { // <-- note the '&'
std::cout << "OK\n";
return xyzzy;
}
int main () {
Vec v;
v[0] = 5;
v[1] = 6;
std::cout << v[22] << '\n';
return 0;
}
The output of this is:
OK
OK
OK
6
In reality, you wouldn't map all indexes to the same value, the code above is simply to illustrate the correct function signature. I haven't bothered to give a more complete example since subclassing classes with non-virtual destructors regularly leads to problems in non-trivial code (b).
(a) It's not usually considered a good idea to subclass std::vector since the destructor isn't virtual, so you can get into trouble when trying to destroy an object polymorphically.
You're probably better off using a has-a relationship (where your class contains a vector) rather than an is-a relationship (where you inherit).
That unfortunately means you may have to create a lot of pass-through methods from your class to the underlying vector (although only the ones you need) but it will solve the problem with the destructor.
(b) See (a) :-)
You'd need to return a reference to your element - however note that even if you did, you'd run into inifinite recursion - your operator[] calls itself.
Either way - inheriting from std::vector isn't a good idea. Use composition instead.
The code below illustrates how to call the operator[] from the vector base class....
#include <iostream>
#include <vector>
struct Vec : std::vector<int>
{
int& operator[](int n)
{
std::cout << "operator[](" << n << ")\n";
return std::vector<int>::operator[](n);
}
};
int main()
{
Vec v;
v.push_back(10);
v.push_back(20);
v[0] += 5;
std::cout << v[0] << ' ' << v[1] << '\n';
}
Output when I run it:
operator[](0)
operator[](1)
operator[](0)
15 20
Don't take all this talk about "do not inherit from std::vector" too seriously: you have to go out of your way to delete a dynamically allocated Vec using a std::vector<int>*, or do an accidental by-value slicing copy - and even then it'd probably only bite you if you had added data members. You should make sure you understand those risks then make your own assessment, but for small utility programs etc. it's productive to inherit from such classes sometimes....