C++ Overloading Operator issue - c++

So here is my header file:
#pragma once
#ifndef HYPERINT_H
#define HYPERINT_H
#include <iostream>
#include <vector>
class Hyperint
{
public:
Hyperint();
Hyperint(long a);
~Hyperint(void);
Hyperint & operator*= (const Hyperint & right);
std::vector<int> hyperintVector;
};
Hyperint operator* (const Hyperint & left, const Hyperint &right);
#endif
here is my cpp file:
#include "stdafx.h"
#include "Hyperint.h"
using namespace std;
Hyperint::Hyperint(long a)
{
//vector<int> hyperint;
int b = a;
while (b != 0){
int h = b % 10;
this->hyperintVector.push_back(h);
b = b / 10;
}
}
Hyperint::~Hyperint()
{
}
Hyperint operator*(const Hyperint & left, const Hyperint & right){
vector<int> leftVec = left.hyperintVector;
vector<int> rightVec = right.hyperintVector;
vector<int> resultVector;
Hyperint result;
int carry = 0;
int counter1 = 0;
for (vector<int>::const_iterator it = leftVec.begin(); it != leftVec.end(); ++it){
int counter2 = 0;
int totalOperand = 0;
for (vector<int>::const_iterator it2 = rightVec.begin(); it2 != rightVec.end(); ++it2){
double pow2 = pow(10, counter2);
totalOperand += ((*it2) * ((int) pow2)) * (*it);
++counter2;
}
totalOperand += carry;
int store = totalOperand % 10;
resultVector.push_back(store);
carry = totalOperand / 10;
++counter1;
}
while (carry != 0){
int putIn = carry % 10;
resultVector.push_back(putIn);
carry /= 10;
}
result.hyperintVector = resultVector;
return result;
}
Hyperint & Hyperint::operator*=(const Hyperint & right){
vector<int> rightVec = right.hyperintVector;
//vector<int> leftVec = this->hyperintVector;
vector<int> resultVector;
Hyperint theResult;
int carry = 0;
int counter1 = 0;
for (vector<int>::const_iterator it = (this->hyperintVector).begin(); it != (this->hyperintVector).end(); ++it){
int counter2 = 0;
int totalOperand = 0;
for (vector<int>::const_iterator it2 = rightVec.begin(); it2 != rightVec.end(); ++it2){
double pow2 = pow(10, counter2);
totalOperand += ((*it2) *((int)pow2)) * (*it);
++counter2;
}
totalOperand += carry;
int store = totalOperand % 10;
resultVector.push_back(store);
carry = totalOperand / 10;
++counter1;
}
while (carry != 0){
int putIn = carry % 10;
resultVector.push_back(putIn);
carry = carry/10;
}
(this->hyperintVector) = resultVector;
return *this;
}
Now the problem arises when I compile it... I get 1 error and I don't know what it is, what it means, or why and how to fix it.
Error 1 error LNK2019: unresolved external symbol "public: __thiscall Hyperint::Hyperint(void)" (??0Hyperint##QAE#XZ) referenced in function "public: class Hyperint & __thiscall Hyperint::operator*=(class Hyperint const &)" (??XHyperint##QAEAAV0#ABV0##Z) C:\Users\Drock\documents\visual studio 2013\Projects\A3-Attempt\A3-Attempt\Hyperint.obj A3-Attempt

It means that the linker is trying to look for a definition of Hyperint::Hyperint() but couldn't find it. You need to provide an implementation of it.
Linker errors can be confusing and a lot more so than compiler errors as the names get garbled and you often lose the exact location in your code that generated that error. Let's go through your error message as it contains all the information you need, just presented poorly. I'll bold the important parts.
Error 1 error LNK2019: unresolved external symbol "public: __thiscall Hyperint::Hyperint(void)" (??0Hyperint##QAE#XZ) referenced in function "public: class Hyperint & __thiscall Hyperint::operator*=(class Hyperint const &)" (??XHyperint##QAEAAV0#ABV0##Z) C:\Users\Drock\documents\visual studio 2013\Projects\A3-Attempt\A3-Attempt\Hyperint.obj A3-Attempt
In human terms, Visual Studio is complaining that it's linker encountered an error called LNK2019, which was due to not being able to find the symbol Hyperint::Hyperint(void), whilst it was going through the function Hyperint::operator*=(class Hyperint const &).
First port of call is the error number. This is easily found in a search engine, which gives the following page on MSDN: http://msdn.microsoft.com/en-us/library/799kze2z.aspx
That page describes what the error is, and gives a few examples of what kind of code generates it. This subpage describes the problem that's closer to yours: http://msdn.microsoft.com/en-us/library/x3k07566.aspx
More specifically, it couldn't find an implementation of Hyperint::Hyperint(). In C++ just declaring it (e.g. in a header as Hyperint();) is not enough, you need an implementation (the code in curly braces {}) somewhere, usually in the corresponding cpp file.
Finally, it's saying that it encountered this error whilst processing the Hyperint::operator*=(class Hyperint const &) function. This information is not actually useful in tracking down this error, but it's probably caused by this line:
Hyperint result;
Which creates a Hyperint object and initialises using the no-argument constructor, i.e. Hyperint::Hyperint().
So putting this all together, you have declared and used the no-argument constructor Hyperint::Hyperint() in your header:
class Hyperint
{
public:
Hyperint(); // < this line here
Hyperint(long a);
~Hyperint(void);
// ...
};
But you have not implemented it in your cpp file. You'd probably need something like this:
Hyperint::Hyperint()
{
// some code goes here, if required
}

You have declared a constructor Hyperint::Hyperint() that takes no arguments, but you have not provided a definition. In the .cpp file you need to provide one. You could also use a default parameter for the Hyperint::Hyperint(long) constructor (in the header file) instead if that works for your design.

Related

Getting error message saying my class does not name a type when trying to overload the "+" operator

The part that is giving me an error message is in the implementation file when I wrote the definition for the friend function that overloads the operator +. It is saying Statistician does not name a type. But it is a friend function and is written in the implementation file where the header is included so I am not sure why it does not recognize this. Also I realize that I spelled statistician wrong for the file name, but don`t know how to easily rename a file in codeblocks.
//header file
#ifndef STATISTICIAN_H
#define STATISTICIAN_H
namespace GREGORY_STOCKER_STATICTICIAN{
class Statistician{
public:
Statistician();
void next_number(double);
void erase_sequence();
int get_length() const {return length_sequence;}
double get_sum() const{return sum;}
double get_mean() const;
double get_largest() const;
double get_smallest() const;
double get_last() const;
friend Statistician operator + (const Statistician &,const Statistician &);
private:
int length_sequence;
double sum;
double smallest;
double largest;
double last;
};
#endif
}
//implementation file
using namespace std;
#include "Statictician.h"
#include <iostream>
#include <cassert>
namespace GREGORY_STOCKER_STATICTICIAN{
Statistician :: Statistician()
{
length_sequence = 0;
sum = 0;
smallest = 0;
largest = 0;
last = 0;
}
void Statistician :: next_number(double num)
{
length_sequence += 1;
sum += num;
if(length_sequence == 1)
{
smallest = num;
largest = num;
}
if (num < smallest)
smallest = num;
if (num > largest)
largest = num;
last = num;
}
void Statistician :: erase_sequence()
{
length_sequence = 0;
sum = 0;
smallest =0;
largest = 0;
last = 0;
}
double Statistician :: get_mean () const
{
assert(length_sequence > 0);
return sum / 2;
}
double Statistician :: get_largest() const
{
assert(length_sequence > 0);
return largest;
}
double Statistician :: get_smallest() const
{
assert(length_sequence > 0);
return smallest;
}
double Statistician :: get_last() const
{
assert(length_sequence > 0);
return last;
}
}
//the part that is tripping the error message
Statistician operator +(const Statistician &s1,const Statistician &s2)
{
Statistician s3;
s3.sum = (s1.sum + s2.sum);
s3.sequence_length = (s1.sequence_length + s2.sequence_length;
if(s1. largest > s2.largest)
s3.largest = s1.largest;
else
s3.smallest = s2.smallest;
if(s1. smallest < s2.smallest)
s3.smallest = s1.smallest;
else
s3.smallest = s2.smallest;
s3.last = s2.last;
return s3;
}
A friend declaration in a class, declares the function in the smallest enclosing namespace. So your friend declaration actually declares and friends GREGORY_STOCKER_STATICTICIAN::operator +. It does not declare nor friend ::operator +.
But your code tries to implement ::operator + outside the namespace. This makes for an entirely different function: it will not be found by any code which tries to add two Statisticians together, because that code only finds the namespaced version. Further, it doesn't even compile (as you posted the error message under Arnav Borborah's answer): since ::operator + is not a friend, it cannot access the private members.
So the simplest solution is in fact to put the operator+ definition inside the namespace, so that it matches the declaration:
namespace GREGORY_STOCKER_STATICTICIAN
{
Statistician operator +(const Statistician &s1,const Statistician &s2)
{
// ...
}
}
Now you don't need to qualify Statistician either.
You have to write the full name of the Statistician class, like this:
GREGORY_STOCKER_STATICTICIAN::Statistician operator +(const
GREGORY_STOCKER_STATICTICIAN::Statistician &s1,const
GREGORY_STOCKER_STATICTICIAN::Statistician &s2)
{
//....
}
Also, you shouldn't have namespace names that long, since it is really verbose (error prone from typos), and it encourages using statements, encouraging naming clashes based errors. 2 using statements for the code would look like this:
using GREGORY_STOCKER_STATICTICIAN::Statistician;
Which is better than the alternative:
using GREGORY_STOCKER_STATICTICIAN;
In addition, while you didn't mention error of this, your if... else blocks need braces, like this:
if(s1. largest > s2.largest)
s3.largest = s1.largest;
else
{
s3.smallest = s2.smallest;
if(s1. smallest < s2.smallest)
s3.smallest = s1.smallest;
else
s3.smallest = s2.smallest;
}
In your previous code, this code would get evaluated outside the block, which I presume you didn't want, even if doesn't make a difference here. As advice, always put braces of if...else blocks, for the sake of maintainability.
Also, since you made your operator+ a friend function, it is limited to the smallest block scope, within the namespace. Make the operator+ an actual member function, not friend, so it looks like this:
Statistician operator+(const s1& other)
{
Statistician s3;
s3.sum = (s1.sum + this->sum);
s3.sequence_length = (s1.sequence_length + this->sequence_length;
if(s1.largest > largest)
s3.largest = s1.largest;
else
s3.smallest = this->smallest;
if(s1.smallest < this->smallest)
s3.smallest = s1.smallest;
else
s3.smallest = this->smallest;
s3.last = s2.last;
return s3;
}
Also, the explicit use of this-> is not required, I was just making evident that the variables were being taken from the current object.

Link error 2019, prototypes are in header file though

I'm new to c++ and was just trying to do a question that involves 3 files.
I got a header file with a namespace that declares a structure and some prototypes. In definitions.cpp file, I have all the function definitions. Then the main.cpp file, just creates a few structures, calls some functions to fill the structures, then calls another function to display the structures.
The problem I have is it gives me an unresolved external error. From what I can gather I think the compiler is complaining that it cant find the prototypes for the functions being called in main.cpp - the overloaded setStruct() and the showStruct().
But I thought when I included the header.h file and declared the functions with the using declaration, in main.cpp, it gave the compiler access to the prototypes stored in the header file?
Header.h
#ifndef header_h
#define header_h
namespace SALES
{
const int QUARTERS = 4;
struct Sales
{
double sales[QUARTERS];
double average;
double max;
double min;
};
void setSales(Sales & s, const double ar[], int n);
void setSales(Sales & s);
void showSales(const Sales & s);
}
#endif
Definitions.cpp
#include<iostream>
#include"header.h"
using SALES::Sales;
using SALES::QUARTERS;
double max(Sales & s) //find max sale value in sales array
{
double maxVal = s.sales[0];
for(int i = 1; i<4;i++)
{
if(s.sales[i]>maxVal)
{
maxVal = s.sales[i];
}
}
return maxVal;
}
double min(Sales & s) //find min sale value in sales array
{
double minVal = s.sales[0];
for(int i = 1; i<4;i++)
{
if(s.sales[i]<minVal)
{
minVal = s.sales[i];
}
}
return minVal;
}
void setSales(Sales & s) // fill sales structure interactivly
{
std::cout<< "Please enter the sales for the yearly quarters.\n";
for(int i = 0;i<QUARTERS;i++)
{
std::cout<< "Quater "<<i+1<<": ";
while(!(std::cin>>s.sales[i]))
{
std::cout<<"Please enter valid input\n";
std::cout<< "Quater "<<i+1<<": ";
std::cin.clear();
std::cin.ignore();
}
}
s.average = ((s.sales[0]+s.sales[1]+s.sales[2]+s.sales[3])/4);
s.max = max(s);
s.min = min(s);
}
void setSales(Sales & s, const double ar[], int n) // fill sales structure non interactivly
{
for(int i = 0;i<n;i++)
{
s.sales[i] = ar[i];
}
for(int i = n;i<QUARTERS;i++)
{
s.sales[i] = 0;
}
s.average = ((s.sales[0]+s.sales[1]+s.sales[2]+s.sales[3])/4);
s.max = max(s);
s.min = min(s);
}
void showSales(const Sales & s) // display structure
{
std::cout<< "\nSales for the year\n";
for(int i = 0;i<QUARTERS;i++)
{
std::cout<<"Quarter "<<i+1<<": $"<<s.sales[i];
}
std::cout<<"Max Sale: "<<s.max<<std::endl;
std::cout<<"Min Sale: "<<s.min<<std::endl;
std::cout<<"Average of sales: "<<s.average<<std::endl;
}
Main.cpp
#include<iostream>
#include"header.h"
using SALES::Sales;
using SALES::setSales;
using SALES::showSales;
int main()
{
double Sales1[4] = {453.50, 654.60, 340.20, 500.30};
Sales Year1;
Sales Year2;
setSales(Year1, Sales1, 3);
setSales(Year2);
showSales(Year1);
showSales(Year2);
return 0;
}
Error
1>------ Build started: Project: Myfirst, Configuration: Debug Win32 ------
1> Main.cpp
1>Main.obj : error LNK2019: unresolved external symbol "void __cdecl SALES::setSales(struct SALES::Sales &,double const * const,int)" (?setSales#SALES##YAXAAUSales#1#QBNH#Z) referenced in function _main
1>Main.obj : error LNK2019: unresolved external symbol "void __cdecl SALES::setSales(struct SALES::Sales &)" (?setSales#SALES##YAXAAUSales#1##Z) referenced in function _main
1>Main.obj : error LNK2019: unresolved external symbol "void __cdecl SALES::showSales(struct SALES::Sales const &)" (?showSales#SALES##YAXABUSales#1##Z) referenced in function _main
1>E:\Documents\Uni\Programming\C++ starter projects\Myfirst\Debug\Myfirst.exe : fatal error LNK1120: 3 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Any help would be great, thanks.
When you define the setSales etc functions, you need to tell the compiler that they are in the SALES namespace. Putting
namespace SALES
{
// functions here
}
will do it.
You are currently defining your functions outside of any namespace, and that is the reason for the linker not finding the definitions within the namespace where those functions are declared and recognized.
The fix would be to wrap the functions in your implementation file - Definitions.cpp -, with the namespace similarly how you are doing it in the header file.
This is what I would write if I were you:
namespace SALES
{
...
void setSales(Sales & s) // fill sales structure interactivly
...
std::cout<<"Average of sales: "<<s.average<<std::endl;
}
}
If you do not put the rest (your min and max) into the namespace, use the :: scope specifier just in case, although I would suggest to put everything into your own namespace.

unresolved external link2019 confusion

I'm trying to resolve an unresolved external (link2019 error). There are many posts on StackOverflow about this issue, but either I am not understanding the error or I am blind to it.
The error is caused by my generate_maze function (specifically by the rand_neighbor() call, right?) but my understanding is that these are all "resolved".
I truncated the code a little bit because it is quite verbose. I hope this was appropriate.
void generate_maze (Vector<int> &coords, Grid<bool> &included, Maze &m);
int main() {
Grid<bool> included = initialize_grid();
Vector <int> coords = rand_coords();
Vector <int> current_point = coords;
generate_maze(coords, included, m);
return 0;
}
void generate_maze (Vector<int> &coords, Grid<bool> &included, Maze &m) {
while (gridIsTrue == false) {
Vector<int> neighbor = rand_neighbor(coords, included);
pointT neighborpoint = {neighbor[0], neighbor[1]};
pointT current_point = {coords[0], coords[1]};
if (included.get(neighbor[0], neighbor[1]) == false) {m.setWall(current_point, neighborpoint, false); included.set(neighbor[0], neighbor[1], true); current_point = neighborpoint;}
}
}
Vector<int> rand_neighbor(Vector<int> &coords, Grid<bool> &included) {
while (1) {
int randomint;
randomint = randomInteger(1,4);
if (randomint == 1) {if (included.inBounds(coords[0], coords[1]+1)) {coords[1] = coords[1]+1; break;}}
if (randomint == 2) {if (included.inBounds(coords[0], coords[1]-1)){coords[1] = coords[1] -1; break;}}
if (randomint == 3) {if (included.inBounds(coords[0] -1, coords[1])){coords[0] = coords[0] -1; break;}}
if (randomint == 4) {if (included.inBounds(coords[0] +1, coords[1])){coords[0] = coords[0] + 1; break;}}
}
return coords;
Error:
error LNK2019: unresolved external symbol "class Vector<int> __cdecl rand_neighbor(class Vector<int>,class Grid<bool> &)" (?rand_neighbor##YA?AV?$Vector#H##V1#AAV?$Grid#_N###Z) referenced in function "void __cdecl generate_maze(class Vector<int> &,class Grid<bool> &,class Maze &)" (?generate_maze##YAXAAV?$Vector#H##AAV?$Grid#_N##AAVMaze###Z)
1>C:\Users\com-user\Desktop\New folder\maze\assign3-maze-PC\Maze\Debug\Maze.exe : fatal error LNK1120: 1 unresolved externals
Using the nice web c++ demangler here you can see that your undefined reference ?rand_neighbor##YA?AV?$Vector#H##V1#AAV?$Grid#_N###Z actually means class Vector __cdecl rand_neighbor(class Vector,class Grid &). The parameters are missing from your error message.
Now, do you see the difference between the declaration and the definition of your function?
class Vector __cdelc rand_neighbor(class Vector,class Grid &);
Vector<int> rand_neighbor(Vector<int> &coords, Grid<bool> &included) { /* ... */}
Let me normalize them a bit:
Vector<int> rand_neighbor(Vector<int>, Grid<bool> &);
Vector<int> rand_neighbor(Vector<int> &, Grid<bool> &) { /* ... */}
You forgot a reference (&) in the prototype of the function! Thus, your definition is of a different function.
As the linker is telling you, the problem is with the rand_neighbor() function. You provided a declaration for it (if you didn't you would get a compiler error rather than a linker error), but you haven't provided a definition.

Visual C++ Linker Error 2019

I'm trying to include a simple hash table class in some files with a header class. But whenever I try to compile I get several errors like this:
LNK2019: unresolved external symbol " public: __thiscall HashTable::~HashTable(void)" (??1HashTable##QAE#XZ) referenced in function _main "
I'm using Visual Studio 2010. I am aware that this means it can't find the function definition in any of the source files. But I have defined them, in a file in the same directory as the file it's called in. Perhaps Visual Studio doesn't look in the current directory unless you set some linker option?
Here is the source code:
//HashTable.h
#ifndef HASH_H
#define HASH_H
class HashTable {
public:
HashTable();
~HashTable();
void AddPair(char* address, int value);
//Self explanatory
int GetValue(char* address);
//Also self-explanatory. If the value doesn't exist it throws "No such address"
};
#endif
//HashTable.cpp
class HashTable {
protected:
int HighValue;
char** AddressTable;
int* Table;
public:
HashTable(){
HighValue = 0;
}
~HashTable(){
delete AddressTable;
delete Table;
}
void AddPair(char* address, int value){
AddressTable[HighValue] = address;
Table[HighValue] = value;
HighValue += 1;
}
int GetValue(char* address){
for (int i = 0; i<HighValue; i++){
if (AddressTable[HighValue] == address) {
return Table[HighValue];
}
}
//If the value doesn't exist throw an exception to the calling program
throw 1;
};
};
No you have not. You created a new class.
The proper way to define the methods is:
//HashTable.cpp
#include "HashTable.h"
HashTable::HashTable(){
HighValue = 0;
}
HashTable::~HashTable(){
delete AddressTable;
delete Table;
}
void HashTable::AddPair(char* address, int value){
AddressTable[HighValue] = address;
Table[HighValue] = value;
HighValue += 1;
}
int HashTable::GetValue(char* address){
for (int i = 0; i<HighValue; i++){
if (AddressTable[HighValue] == address) {
return Table[HighValue];
}
}
//If the value doesn't exist throw an exception to the calling program
throw 1;
};

LNK2019 error, unresolved external symbol

The error verbatim reads
1>yes.obj : error LNK2019: unresolved external symbol "int __cdecl availableMoves(int * const,int (* const)[4],int)" (?availableMoves##YAHQAHQAY03HH#Z) referenced in function "void __cdecl solveGame(int * const,int (* const)[4])" (?solveGame##YAXQAHQAY03H#Z)
I've never seen this error before. Here are the two functions I believe it's referring to though.
int availableMoves(int a[15], int b[36][3],int openSpace){
int count=0;
for(int i=0; i<36;i++){
if(i < 36 && b[i][2] == openSpace && isPeg(b[i][0],a) && isPeg(b[i][1],a) ){
count++;
}
}
return count;
}
and
void solveGame(int a[15], int b[36][4]) {
int empSpace;
int movesLeft;
if(pegCount(a) < 2) {
cout<<"game over"<<endl;
} else {
empSpace = findEmpty(a);
if(movesLeft = availableMoves(a,b,empSpace) < 1 ) {
temp[index] = empSpace;
d--;
c[d][0] = 0;
c[d][1] = 0;
c[d][2] = 0;
c[d][3] = 0;
a[b[c[d][3]][0]] = 1;
a[b[c[d][3]][0]] = 1;
a[b[c[d][3]][0]] = 0;
b[c[d][3]][3] = 0;
index++;
} else if(movesLeft >= 1) {
chooseMove( a, b, empSpace);
index = 0;
for(int i=0; i<4; i++) {
temp[i] = -1;
}
}
d++;
solveGame( a, b);
}
}
Your current declaration doesn't match the definition.
You probably have declared the function availableMoves() before you use it, but then you implement a different function:
int availableMoves(int* const a, int (* const)[4] , int);
//....
//....
//....
//code that uses available moves
int availableMoves(int a[15], int b[36][3],int openSpace)
{
//....
}
Since the compiler sees that declaration first, it will use it to resolve the call in the block of code. However, that function is not exported, as it has a different signature.
in solved game
b[36][4]
in available moves
b[36][3]
that could create a problem.
Nice one: you use incompatible array dimensions! Note that part of the error message reads
availableMoves(int *const,int (*const)[4],int)
While the definition of availableMoves() looks like this:
int availableMoves(int a[15], int b[36][3],int openSpace)
Although the first dimension of the arguments is ignored, all other dimensions have to match exactly. You try to call this function with incompatible dimensions, however:
void solveGame(int a[15], int b[36][4]){
...
... availableMoves(a,b,empSpace) ...