Problems with functions in classes C++ (LNK2019 & LNK1120 errors) - c++

I've been working on a project for my college class that uses classes in c++, unfortunately anytime I try to call on a function that is passed parameters within my class the program fails to compile with the two following errors:
Error LNK2019 unresolved external symbol "int __cdecl binsearch(class Course * * const,int,char * const)" (?binsearch##YAHQAPAVCourse##HQAD#Z) referenced in function _main Project1 C:\Users\cvos\source\repos\Project1\Project1\courses_main.obj 1
and
Error LNK1120 1 unresolved externals Project1 C:\Users\cvos\source\repos\Project1\Debug\Project1.exe 1
I've looked up the LNK problems, and most results suggest it's something related to symbols in c++ vs c (That fix doesn't work) or that there is a problem with linking the files within visual studio (That fix also didn't work), and finally that it was something to do with it needing to be on the console subsystem (Which it already was).
The strange thing is, if I comment out my calls to all of the functions I've made in the "Course" class that are passed parameters, the program runs fine. It's only when I am trying to use the functions created in the "Course" class that the program fails to run, leading me to suspect strongly I'm doing something wrong with how I'm passing variables to my member functions.
I'll post the relevant parts of my code:
Within my header file "courses.h" I declare my function:
int binsearch(Course* co_ptr[], int size, char search[]);
Within my 2nd source file "courses_functions.cpp" I define the function:
int Course::binsearch(Course* co_ptr[], int size, char search[])
{
int low = 0, high = size - 1, first_index = -1, last_index = -1, num_of_entries = 0;
while (low <= high)
{
int mid = (low + high) / 2;
if (co_ptr[mid]->name == search)
{
bool found = false;
int i = mid;
while (!found) //Check values below mid
{
if (co_ptr[i]->name == search)
{
first_index = i; //first_index now holds a potential first occurence of our name
if (i == 0)
{
found = true;
}
}
else
{
found = true;
}
i--; //decrement i and check again.
}
i = mid; //Reset i
found = false; //Reset found
while (!found) //Check values above mid
{
if (co_ptr[i]->name == search)
{
last_index = i; //last_index now holds a potential last occurence of our name
if (i == size - 1)
{
found = true;
}
}
else
{
found = true;
}
i++; //increment i and check again.
}
break; //Breaks us out of the main while loop
}
else if (co_ptr[mid]->name < search)
{
low = mid + 1;
}
else
{
high = mid - 1;
}
}
if ((first_index != -1) && (last_index != -1))
{
for (int i = first_index; i <= last_index; i++)
{
std::cout << "\nEntry found: "
<< std::endl << co_ptr[i]->name << ' ' << co_ptr[i]->units << " units, grade:" << co_ptr[i]->grade;
num_of_entries++;
}
return num_of_entries;
}
else
{
std::cout << "\nEntry not found.";
return num_of_entries;
}
}
Lastly in my main source file "courses_main.cpp" I call the function:
else if (selection == 3) //Display a course
{
char title[50] = "";
int results = 0;
std::cout << "\nEnter a class to search for: ";
std::cin.getline(title, 50, '\n');
std::cin.ignore();
results = binsearch(courses, size, title);
}
As this is for a college class, I'm not looking to use any alternative methods, I'm mainly trying to figure out why the method I'm using would return the errors I shared above, but I will gladly post more snippets of my code if it is necessary.
Thanks!

The cause is almost certainly one of the following:
You're not compiling the implementation file (just using the header elsewhere).
You're compiling the implementation, but not using the compiled object in the linking of objects into the executable.
You have some minor mismatch in naming, e.g. using binsearch() not in a class context, or using a slightly different signature somehow (not likely giving what you've told us).

Need to see a declaration of your "courses.h" file. You may have declared binsearch outside of your Course class declaration. In which case you will get a linker error as mentioned.
Based on your usage in main.. your implementation of this function need not be in Course class, it can be a standalone function outside of Course class. once you move your function definition outside of Course class, your linker should go away, provided you have courses_functions.cpp and courses_main.cpp files in same project in your MSVC IDE.

Related

C++ There is a bool return type function returning (24) here

First of all sorry for too much code
Here there is a vector (teamNum) with type class, the class contain a vector (player) with type struct, it is a little complicated, but here in this function I need to check if there is a player in teamNum which contain tName equal to _tname (function parameter) contain (the player) pID equal to _pID (function parameter)
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
if (teamNum[i].tName == _tname)
{
for (int j = 0; j < teamNum[i].player.size(); j++)
{
if (teamNum[i].player[j].pID == _pID)
return true;
}
}
else if (i == (teamNum.size() - 1))
{
return false;
}
}
}
And in the main
int main()
{
cout << "\n" << thereIsSimilarID("Leverpool", 1) << endl;
}
The output is 24 !!!!!
(good note that this happen just when the team (Leverpool) is the last team in the vector teamNum)
Again sorry for too much code but I need to know the bug not only fix the problem I need to learn from you
You encountered undefined behaviour.
If you take the if (teamNum[i].tName == _tname)-branch on the last element, but find no player with the correct pID, you don't return anything. Which means, that the return value is whatever random value is currently in the memory location that should hold the return value. In your case it happens to 24. But theoretically, everything could happen.
The same problem occurs when teamNum is empty.
The solution is to make sure to always return a value from a function (except if it has return type void of course):
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
// In this loop return true if you find a matching element
}
// If no matching element was found we reach this point and make sure to return a value
return false;
}
You should take a look at your compiler settings and enable all the warnings. And often it's good to let it treat certain warnings as errors.

list requires class type

So I'm trying to make a bubble sort algorithm in class and I'm having this problem where it keeps giving me an error when I'm trying to find the length of the list where it says "expression must have a class type" and for the life of me I cannot figure out what to do. the tutorial I'm using isn't an help and I cannot find any other people with the same problem.
if anyone gets what it is asking I would appreciate the help, and any explanation would also be appreciated as I'm still new and would like to understand so I can try to learn
this was all done on VS 2017 (the free version)
#include "pch.h"
#include <iostream>
using std::cout;
using std::endl;
int main()
{
bool found = true;
int target{ 0 };
int temp{};
bool ordered{ false };
int list[10] = { 4,6,5,1,3,2,10,8,9,7 };
cout << list.length() << endl;
bool swapped{ false };
while (ordered = false)
{
target = 0;
while (target != list.length)
{
if (list[target] > list[target + 1])
{
swapped == true;
list[target] = temp;
list[target] = list[target + 1];
list[target + 1] = temp;
target = target + 1;
}
else
{
target = target + 1;
}
}
if (swapped == false)
{
ordered = true;
}
}
cout << list << endl;
getchar();
return 0;
}
link to the photo of the error message
The error you have mentioned ("expression must have a class type") is caused by the below statement and other similar statements :
cout << list.length() << endl;
list is an integer array of size 10 as per this statement int list[10];
So you cannot use a . on it. You can use the . operator on a structure or class or union only. And even if list were a class/structure, length() method should be defined in it for the above to work.
Instead you should use sizeof operator. You can store it in a variable and use it later on.
size_t length = sizeof list/sizeof list[0];
cout << length << endl;

constructors / Lab 9 Problems [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 5 years ago.
My professor wants us to create a gladiator simulation where we name 5 gladiators, then create their stats, create the boss stats, then allow for the gladiators to fight the boss. During the fight, the health of everyone and randomly generated number damage dealt will be displayed until a winner is decided and from there, we will prompt the user if they would want a rematch.
Currently, I am stuck on figuring out what is and how do I use a constructor. Overall, I am lost with the project in total, but for now I want to understand this step by step. Inside the BossFight.h, consists of the prototype functions.
class BossFight {
private:
//Holds the party of gladiators that is banded together to fight the boss
Gladiator party[PSIZE];
//Holds the powerful boss that the party is fighting
Gladiator boss;
//Variables used for record keeping
int turnNum, fightsStarted, fightsWon;
//Will fill the party with gladiators, this function can call/reuse the createGladiator function.
void getParty();
//Will generate a boss for the party to fight. Has no crit or evasion, but 3* damage min and range, and 6* health
void getBoss();
//Tells the user who won, after how many turns, and the current record for the session
void displayFightResults(bool partyWon);
//One turn occurs, where each party member attacks the boss, then the boss attacks the party.
//Returned value indicates status of fight (continue, party win, party loss)
//Boss will randomly choose between attacking a single (randomly chosen) party member for full damage, or
//attacking the full party for half damage.
int takeTurn();
//Handles dealing damage to the entire party
void bossAttacksArea();
public:
//Responsible for generating the party and the boss, should initialize the other
//private variables as well
BossFight();
//User calls this when they want to run a fight. It will ask them if they want to use
//the same party, or get a new one.
void runFight();
};
What I have done so far is
#include <iostream>
#include <string>
#include "BossFight.h"
#include <stdlib.h>
#include <time.h> // Allows seed to generate new random numbers every time.
using namespace std;
const int SIZE = 5; //Party Size
Gladiator createGladiator(string name) // Data type Gladiator with its data named createGladiator
{
Gladiator stats; // Structure tag
for (int i = 0; i < SIZE; i++)
{
int maxHealth, evasion, critical;
stats.name = name;
// set max health
switch (rand() % 3) // % 3 means the range. So the starting number is 0 and final number is 2. Used to find a random number between the range 0-2.
// Uses that random number to open up one of the cases.
{
case 0: stats.maxHealth = 150;
break;
case 1: stats.maxHealth = 200;
break;
case 2: stats.maxHealth = 250;
break;
}
// set evasion
int numE = (rand() % 5); // Used to find a random number between the range 0-4.
switch (numE) // Uses that random number to open up one of the cases.
{
case 0: stats.evasion = 50;
break;
case 1: stats.evasion = 75;
break;
case 2: stats.evasion = 100;
break;
case 3: stats.evasion = 125;
break;
case 4: stats.evasion = 150;
break;
}
// Set Critical
int numC = (rand() % 5); // Used to find a random number between the range 0-4.
switch (numC) // // Uses that random number to open up one of the cases.
{
case 0: stats.critical = 50;
break;
case 1: stats.critical = 75;
break;
case 2: stats.critical = 100;
break;
case 3: stats.critical = 125;
break;
case 4: stats.critical = 150;
break;
}
// Set minDamage
int minimum, maximum;
minimum = 8;
maximum = 5;
int numMin = (minimum + rand() % (maximum + minimum)); // Used to find a random number between the minimum and maximum values.
stats.dmgMin = numMin;
// set DamageRange
int maxMin, maxMax;
maxMin = 16;
maxMax = 5;
int numMax = (maxMin + rand() % (maxMax - maxMin)); // Used to find a random number between the minimum and maximum values.
stats.dmgRange = numMax;
return stats; //Return all of the stats into the structure tag.
}
}
BossFight::BossFight() ***< -- stuck right here ***
{
getParty();
}
void BossFight::getBoss()
{
getBoss();
}
void getParty(string name[])
{
{
cout << "To begin with, enter 5 gladiator's name" << endl; // First for loop asking user for array input.
for (int i = 0; i < SIZE; i++)
{
cin >> name[i];
}
for (int i = 0; i < SIZE; i++)
{
cout << "Gladiator " << i + 1 << " name is " << endl;
cout << name[i] << endl;
}
}
}
int main()
{
srand(time(NULL)); //initiate random number generator seed.
string name[SIZE];
cout << "Hello user" << endl;
BossFight();
system("PAUSE");
}
I would appreciate any type of help. Do remember that I am taking an intro to computer science class, so I may not understand complex coding yet. I have been doing fine so far interpreting how the code should work in english, but find it hard to interpret how it should be via code.
Also, I am getting an error
Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol "private: void __thiscall
BossFight::getParty(void)" (?getParty#BossFight##AAEXXZ) referenced in
function "public: __thiscall BossFight::BossFight(void)"
(??0BossFight##QAE#XZ) ConsoleApplication6 Severity Code Description Project File Line Suppression
State Error LNK2019 unresolved external symbol "private: void
__thiscall BossFight::getParty(void)" (?getParty#BossFight##AAEXXZ) referenced in function "public: __thiscall BossFight::BossFight(void)"
(??0BossFight##QAE#XZ) ConsoleApplication6 C:\Users\1\documents\visual
studio 2017\Projects\ConsoleApplication6\ConsoleApplication6\1.obj 1
And was wondering what even caused this? All i have in my visual studio is my header and cpp file.
This is called a linker error. What the error is saying is that BossFight::getParty() is being used by the BossFight::BossFight() constructor implementation, but you haven't provided an implementation of the getParty() method.
It looks like you were trying to add an implementation by declaring and implementing a getParty(std::string*) function, but this is not an implementation of the BossFight::getParty() method.
To implement BossFight::getParty(), you will need something like:
void BossFight::getParty() {
// implementation here
}
You will probably also want to hang on to the BossFight object that you construct by giving it a name:
BossFight boss_fight; // This declares *and* constructs a BossFight object on the stack.

Linking error while using static library linkage

This might have been asked previously, however, I found it only in context of Classes, and this is not the case.
Utils.h
#ifndef _UTILS_H_
#define _UTILS_H_
#include <cmath>
//is 'x' prime?
bool isPrime(long long int x);
//find the number of divisors of 'x' (including 1 and x)
int numOfDivisors(long long int x);
#endif //_UTILS_H_
Utils.cpp
#include "Utils.h"
bool isPrime(long long int x){
if (x < 2){
return false;
}
long double rootOfX = sqrt( x );
long long int flooredRoot = (long long int)floor ( rootOfX );
for (long long int i = 2; i <= flooredRoot; i++){
if (x % i == 0){
return false;
}
}
return true;
}
int numOfDivisors(long long int x){
if (x == 1){
return 1;
}
long long int maxDivisor = (x / 2) + 1;
int divisorsCount = 0;
for (long long int i = 2; i<=maxDivisor; i++){
if (x % i == 0){
divisorsCount++;
}
}
divisorsCount += 2; //for 1 & x itself
return divisorsCount;
}
These two files have been compiled with Visual Studio 2012 in Debug mode as a static library.
Now I try to use them in a separate project, let's call it MainProject:
1. Add the "Utils.vcproj" to MainProject solution.
2. Make MainProject to depend on Utils
3. In "Properties"->"Linker"->"Input"->"Additional Dependencies" put the path to Utils.lib
Here is the main which uses Utils:
#include <iostream>
#include "..\Utils\Utils.h"
using namespace std;
int main(){
cout << "num of divisors of " << 28 << ": " << numOfDivisors(28) << endl;
//this part is merely to stop visual studio and look at the output
char x;
cin >> x;
return 0;
}
And this is the error I get:
Error 1 error LNK2019: unresolved external symbol "int __cdecl numOfDivisors(__int64)" (?numOfDivisors##YAH_J#Z) referenced in function _main G:\ProjectEuler\Problem12\Source.obj Problem12
Why can't it find the code which implements "numOfDivisors"? I have given it the .lib which contains it, moreover - put a dependency on the Utils project itself...
Any help would be appreciated.
Assuming the library is correctly built and linked, the next most likely cause of the error is that the function is named something else in the library than it is in the code that links to it.
This could be caused by any number of project settings that affect either name decoration or type names. There's not really any point in guessing from a distance which particular setting is the culprit in your case. You can compare the two projects' properties (either manually or with a diff tool) and try to spot a difference that would result in a different decorated function name.
Looks like method numOfDivisors() is not defined in you Utils.cpp, can you check it once?
And why is your compiler complaining "G:\ProjectEuler\Problem12\Source.obj"? Where is Source.obj coming from?
You have to specify library path in one field and library name in other field, have you specified both under appropriate settings?

dynamic_bitset, crash my program

I'm new with boost. I have a program which uses dynamic_bitset inside a lambda function. After I try to run the program, I get this message. This message appears even without the function that initializes the bitset and the functions that handle it.
Does anybody know what this message means and what might be the problem?
The message:
/usr/include/boost/dynamic_bitset/dynamic_bitset.hpp:616: boost::dynamic_bitset<Block, Allocator>::~dynamic_bitset() [with Block = long unsigned int, Allocator = std::allocator<long unsigned int>]: Assertion 'm_check_invariants()' failed.
Aborted
well the code is something like this
main call to this function :
int Molecule::initSimilarity(int depth){
cout << "_size is: " << _size << "\t depth is: " << depth << endl; //TODO delete
AtomSet viewing(_size);
int m = 0;
{
// break into initial groups by symbol and valancy
for(int i=0 ; i<_size ; i++)
{
if(viewing[i]) continue;
AtomSet mask = getSetMask( //AtomSet is typedef for dynamic_bitset
[&](const Atom& b)->bool
{
return (!viewing[b._index] && b._valence == _atoms[i]->_valence && strcmp(b._symbol, _atoms[i]->_symbol) == 0);
},
[&](Atom &b)
{
b._class = m; //set the equivalence class of atom 'b' to 'm'
}
);
m++;
viewing |= mask; //viewing now contains a set of atoms and for each atom it's equivalence class
}
cout << "number of equivalence class: " << m << endl; //TODO DELETE!
}
for (int j = 0; j < depth ; j++){
AtomSet viewed(_size);
int before = m;
// iteratively refine the breakdown into groups
for (int i = 0 ; i < _size ; i++) //for any atom A
{
if (viewed[i]) continue;
viewed.flip(i);
AtomSet mask = getSetMask(//put all atoms which are equivalnt but not similar to A in
//their own equivalence class
[&](const Atom& b)->bool
{
if (viewed[b._index])
return false; //if b is in viewed return false;
if (_atoms[i]->_class == b._class) //if in the same class add b to viewed
{
viewed.flip(b._index);
bool similar = !isSimilar(*_atoms[i],b);
return similar;
}
return false;
},
[&m](Atom& b)
{
b._class = m;
}
);
if (!mask.none()) m++;
}
if (before == m){
std::cout << "Finished early after just " << j << " iterations" << std::endl;
return m;
}
}
return m;
}
the signature of getSetMask is:
AtomSet getSetMask(std::function property, std::function action);
and the weirdest thing that even when i remove all the content of that function it still give me the error message
Probably the dynamic_bitset variable that you are referencing in the lambda has gone out of scope and has already been destroyed, or something similar. (Without the source code it's difficult to be more specific)
I had that problem and it took me 3 hours to find out the problem. Here is what can happen: The operator[] in dynamic_bitset does not do bound checking. So, one value can be assigned outside of allowed range and this does not create any error (sanitizer/valgrind do not see anything) since dynamic_bitset is using 64 bit integers (on my computer at least) in order to store values. So, you can get a stored integer of 32 while you allowed only 4 bits in the dynamic_bitset. The error is triggered at a later time when m_check_invariant() is called for example when the destructor is called.
So, the problem becomes to find this range error. The solution is to edit the boost/dynamic_bitset.hpp and add print statement in the code of operator[] when an operation out of range is called. If you cannot do that then download the boost library and install it in your home directory.
I had a similar problem with dynamic_bitset that was solved by calling reset() on it before it got destroyed.
That can indicate that you are writing past the end of the bitset without resizing it. Might want to do some bounds checking.
Read the explaination of Mathieu Dutour Sikiric. The problem is that you write outside of allowed range of the bitset via operator[] and this does not create any error because it's boost and it doesn't bother to waste compute time checking that you have right to write where you want. It is C++ you know...
So to detect it, go to boost/dynamic_bitset/dynamic_bitset.hpp, and modify the code to impose checks every time you use operator[].
boost/dynamic_bitset/dynamic_bitset.hpp, around line 300.
reference operator[](size_type pos) {
assert(m_check_invariants());
return reference(m_bits[block_index(pos)], bit_index(pos));
}
bool operator[](size_type pos) const {
assert(m_check_invariants());
return test(pos);
}
This makes it easier to detect the error in your code.