In an attempt to code a basic 'Bank Account' class separated into a header file, and two .cpp files the following error messages are displayed when attempting to compile.
(Developing in vim through the terminal (OS X Yosemite 10.10.5))
I am not sure what the error messages are referring to nor how to solve the issue. Thanks in advance for any insight and feedback.
Terminal Command & Error Messages:
$ g++ -std=c++11 -Wall Account.cpp
$ g++ -std=c++11 -Wall test.cpp
Account.h
//Account.h
//Account class definition. This file presents Account's public
//interface without revealing the implementation of Account's member
//functions, which are defined in Account.cpp.
#ifndef ACCOUNT_H
#define ACCOUNT_H
#include <iostream>
class Account
{
public:
Account(int amount); //constructor initialize accountBalance
void credit(int creditValue); //credits the account balance
void debit(int debitValue) ; //debits the account balance
int getBalance() const; //gets the account balance
private:
int accountBalance;//account balance for this Account
};//end class Account
#endif
Account.cpp
//Account.cpp
//Account member function definitions. This file contains
//implementations of the member functions prototype in Account.h
#include <iostream>
#include "Account.h" //include definition of class Account
using namespace std;
//constructor initializes accountBalance with int supplied
//as argument
Account::Account(int amount)
{
if(amount >= 0)
{
accountBalance = amount;
}
else
{
accountBalance = 0;
cerr << "The initial balance was invalid" << endl;
}
}
//function to credit amount to account balance
//value must be greater than zero
void Account::credit(int creditValue)
{
if(creditValue > 0)
{
accountBalance += creditValue;
}
else
{
cout << "Credit value cannot be negative nor zero.\n";
}
}
//function to debit amount from account balance
//value cannot exceed current account balance
void Account::debit(int debitValue)
{
if(accountBalance >= debitValue)
{
accountBalance -= debitValue;
}
else
{
cout << "Debit amount exceeds account balance.\n";
}
}
//function to get the account balance
int Account::getBalance() const
{
return accountBalance;
}
test.cpp
#include <iostream>
using namespace std;
// include definition of class Account from Account.h
#include "Account.h"
// function main begins program execution
int main()
{
Account account1( 50 ); // create Account object
Account account2( 25 ); // create Account object
Account account3( -25 ); // attempt to initialize to negative amount;
// display initial balance of each object
cout << "account1 balance: $" << account1.getBalance() << endl;
cout << "account2 balance: $" << account2.getBalance() << endl;
int depositAmount; // stores deposit amount read from user
cout << "\nEnter deposit amount for account1: "; // prompt
cin >> depositAmount; // obtain user input
cout << "\ndeposit " << depositAmount
<< " into account1 balance\n\n";
account1.credit( depositAmount ); // add to account
return 0; // indicate successful termination
} // end main
The problem is that you're compiling each .cpp file as if it were the only file in the program. Instead, you must use the -c option to your C++ compiler (assuming GCC or Clang) to compile each .cpp file. This will give you a corresponding set of .o (object) files. You then link these together with a final command line like this:
g++ -o myprogname Account.o test.o
If you use a build tool like CMake, these details will be handled automatically.
Related
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 11 months ago.
This is basically two errors in one, that seem to come from the same thing. If I define my functions in my main.cpp file, and forward declare them at the top of the file, it doesn't give me any errors and everything runs smoothly.
When trying to declutter and move things into seperate .cpp files, it starts to give me linker errors and saying things are undefined even though I am using appropriate header files. The code is shown below:
main.cpp
#include "io.h"
#include <iostream>
#include <map>
class exchangeRates;
void menu();
int main()
{
menu();
return EXIT_SUCCESS;
}
// class storing exchange rates
class exchangeRates
{
public: // Access specifier
// Data Members
std::map<std::string, double> usd = {
{"GBP", 1.2},
{"EUR", 0.7},
};
std::map<std::string, double> gbp = {
{"USD", 0.9},
{"EUR", 1.4},
};
};
// menu function
void menu()
{
// get reference currency code from user
std::string refCurrency{ obtainCodeFromUser() };
// create 'rates' instance of 'exchangeRates' class
exchangeRates rates{};
// print the exchange values for that currency
if (refCurrency == "USD")
{
printExchangeValues(rates.usd, refCurrency);
}
else if (refCurrency == "GBP")
{
printExchangeValues(rates.gbp, refCurrency);
}
else
{
std::cout << "\nInvalid currency code. Example: USD, GBP, EUR etc.\n\n";
menu();
}
}
io.h
#ifndef IO_H
#define IO_H
#include <iostream>
#include <map>
std::string obtainCodeFromUser();
double obtainAmountFromUser();
template<typename Map>
void printExchangeValues(Map& valuedCurrencies, std::string refCurrency);
#endif
io.cpp
#include "io.h"
#include <iostream>
#include <map>
// io functions for currency converter
std::string obtainCodeFromUser()
{
// obatin reference currency code from user
std::cout << "Enter currency code for reference currency (case-sensitive): ";
std::cin.clear();
std::string refCurrency{};
std::cin >> refCurrency;
std::cin.ignore(INT_MAX, '\n');
return refCurrency;
}
double obtainAmountFromUser()
{
// obtain amount of currency to be converted from user
std::cout << "Enter amount of currency to convert: ";
std::cin.clear();
double amount{};
std::cin >> amount;
std::cin.ignore(INT_MAX, '\n');
return amount;
}
template<typename Map>
void printExchangeValues(Map& valuedCurrencies, std::string refCurrency)
{
// obtain amount of currency to be converted
double amount{ obtainAmountFromUser() };
std::cout << refCurrency << " " << amount << " is worth:\n";
for (auto& item : valuedCurrencies) {
std::cout << item.first << ": " << amount * item.second << '\n';
}
}
I am still a beginner with C++ so some parts have been copied from other open-source programs, and I know there are probably plenty of places to improve my code, but I'm mainly interested in why it just won't compile. The examples I followed when learning how to use header files worked fine and I don't believe I've done anything different here.
It says the identifiers "obtainCodeFromUser" and "printExchangeValues" are undefined.
The linker error it gives is LNK2019 'unresolved external symbol ...' and it seems to be relating to the printExchangeValues function.
Any help is massively appreciated!
The issue mentioned by WhozCraig is very useful, I hope you will read it carefully. Regarding your question, after I modified some code, the program can run correctly. The error is caused by the template. Since you are a beginner and the program is not very complicated, the following code is more convenient for you to understand:
main.cpp
#include "io.h"
#include <iostream>
#include <map>
// class storing exchange rates
class exchangeRates
{
public: // Access specifier
// Data Members
std::map<std::string, double> usd = {
{"GBP", 1.2},
{"EUR", 0.7},
};
std::map<std::string, double> gbp = {
{"USD", 0.9},
{"EUR", 1.4},
};
};
template<typename Map>
void printExchangeValues(Map& valuedCurrencies, std::string refCurrency)
{
// obtain amount of currency to be converted
double amount{ obtainAmountFromUser() };
std::cout << refCurrency << " " << amount << " is worth:\n";
for (auto& item : valuedCurrencies) {
std::cout << item.first << ": " << amount * item.second << '\n';
}
}
// menu function
void menu()
{
// get reference currency code from user
std::string refCurrency{ obtainCodeFromUser() };
// create 'rates' instance of 'exchangeRates' class
exchangeRates rates{};
// print the exchange values for that currency
if (refCurrency == "USD")
{
printExchangeValues(rates.usd, refCurrency);
}
else if (refCurrency == "GBP")
{
printExchangeValues(rates.gbp, refCurrency);
}
else
{
std::cout << "\nInvalid currency code. Example: USD, GBP, EUR etc.\n\n";
menu();
}
}
int main()
{
menu();
return EXIT_SUCCESS;
}
io.h
#ifndef IO_H
#define IO_H
#include <iostream>
#include <map>
std::string obtainCodeFromUser();
double obtainAmountFromUser();
#endif
io.cpp
#include "io.h"
#include <iostream>
#include <map>
// io functions for currency converter
std::string obtainCodeFromUser()
{
// obatin reference currency code from user
std::cout << "Enter currency code for reference currency (case-sensitive): ";
std::cin.clear();
std::string refCurrency{};
std::cin >> refCurrency;
std::cin.ignore(INT_MAX, '\n');
return refCurrency;
}
double obtainAmountFromUser()
{
// obtain amount of currency to be converted from user
std::cout << "Enter amount of currency to convert: ";
std::cin.clear();
double amount{};
std::cin >> amount;
std::cin.ignore(INT_MAX, '\n');
return amount;
}
new to c++.Im stuck with a question here, i made a bank account program which has functions like withdraw() and deposit() defined in a class called 'account'.So, i defined my class in a different file(account.h) also i defined withdraw() inside the class itself but defined the deposit() function outside the class in 'account.cpp' file.When i compile it i get the following error -
undefined reference to 'account::deposit(int)'
I'm not an expert but i think it doesn't recognize that i defined the define() function int account.cpp.Also i use vscode (idk if that helps).
here is the code-
main.cpp
#include <iostream>
#include <string>
#include <vector>
#include "account.h"
int main()
{
account Ajay_bank;
if (Ajay_bank.withdraw(1000))
{
std::cout << "withdraw successful\n";
}
else
{
std::cout << "withdraw failed";
}
if (Ajay_bank.deposit(2000))
std::cout << "Deposit successful";
else
std::cout << "[error - NET404]:try again later";
}
account.cpp-
#include "account.h"
bool account::deposit (int amount)
{
balance += amount;
return true;
}
account.h-
#ifndef _ACCOUNT_H
#define _ACCOUNT_H
#include <string>
class account
{
private:
std::string name;
int balance {200};
int credit_score {};
public:
bool withdraw (int amount)
{
if (balance - amount >= 0)
{
balance -= amount;
return true;
}
else
return false;
}
bool deposit (int amount);
};
#endif
Thanks.
While compiling more than source file (.cpp) you should compile with that files.
g++ main.cpp account.cpp -o main
then run it like:
./main
If you try with that command you can run successfully
I am trying to practice object oriented programming structure in c++. I have written some piece of code. But I got an undefined reference error.
I've tried to build with clion ide but it gave me error. I've tried to compile it on linux terminal using g++ command but it gave me same error.
Account.h
#ifndef ACCOUNT_H
#define ACCOUNT_H
class Account
{
public:
Account ();
Account(double init_balance);
double getBalance();
void deposit(double amt);
void withdraw(double amt);
private:
double balance;
};
#endif // ACCOUNT_H
Account.cpp
#include "Account.h"
#include <iostream>
using namespace std;
Account::Account(double init_balance)
:balance(init_balance)
{
}
double Account::getBalance(){
return balance;
}
void Account::deposit(double amt){
balance += amt;
}
void Account::withdraw(double amt){
balance -= amt;
}
Customer.h
#ifndef CUSTOMER_H
#define CUSTOMER_H
#include "Account.h"
#include <iostream>
#include <string>
using namespace std;
class Customer
{
public:
Customer(string first_Name, string last_Name) :
firstName(first_Name), lastName(last_Name)
{
}
//Customer(string first_Name, string last_Name);
string getFirstName();
string getLastName();
Account getAccount();
void setAccount(Account acc);
private:
string firstName;
string lastName;
Account account;
};
#endif // CUSTOMER_H
Customer.cpp
#include "Customer.h"
#include <iostream>
#include <string>
using namespace std;
string Customer::getFirstName(){
return firstName;
}
string Customer::getLastName(){
return lastName;
}
Account Customer::getAccount(){
return account;
}
void Customer::setAccount(Account acc)
{
account = acc;
}
main.cpp
#include "Account.h"
#include "Customer.h"
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
Customer *customer;
Account account(0.0);
// Create an account that can has a 500.00 balance.
cout << endl << "Creating the customer Jane Smith.";
customer = new Customer("Jane", "Smith");
cout << endl << "Creating her account with a 500.00 balance.";
customer->setAccount(Account(500.00));
account = customer->getAccount();
cout << endl << "Withdraw 150.00";
account.withdraw(150.00);
cout << endl << "Deposit 22.50";
account.deposit(22.50);
cout << endl << "Withdraw 47.62";
account.withdraw(47.62);
// Print out the final account balance
cout << endl
<< "Customer ["
<< customer->getLastName()
<< ", "
<< customer->getFirstName()
<< "] has a balance of "
<< account.getBalance()
<< endl;
delete customer;
Account acc1(100), acc2(200);
double suAcc = acc1.getBalance()+ acc2.getBalance();
Account sumAcc(suAcc);
cout << "Balance of sumAcc is " << sumAcc.getBalance() << endl;
return (EXIT_SUCCESS);
}
Here is the error:
/cygdrive/c/Users/James/CLionProjects/untitled13/main.cpp:9: undefined reference to `Account::Account(double)'
/cygdrive/c/Users/James/CLionProjects/untitled13/main.cpp:9:(.text+0x2f): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `Account::Account(double)'
/cygdrive/c/Users/James/CLionProjects/untitled13/main.cpp:15: undefined reference to `Account::Account(double)'
/cygdrive/c/Users/James/CLionProjects/untitled13/main.cpp:15:(.text+0x12e): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `Account::Account(double)'
/cygdrive/c/Users/James/CLionProjects/untitled13/main.cpp:15: undefined reference to `Customer::setAccount(Account)
'
It goes on with every method.
I was able to compile this after making several changes.
Remove using namespace std from customer.h. It's bad practice to use "using namespace" here as it could cause name collisions when another file includes customer.h. As a result of removing "using namespace std" you'll need to qualify all of your strings as std::string instead of string.
You declared a default constructor for Account but there is no implementation provided. When a customer is created it tries to call the default constructor of account. If you are on a newer version of c++ you can change this line in your header file.
Account();
to
Account() = default;
If you're on an older version add this to Account.cpp
Account(){}
Here's my code and the errors I'm receiving - any help would be appreciated.
There's something wrong with getNextAcountNumber. I have tried to assign the value of account ID but it has not worked since it is a private member.
Error 1 error LNK2019: unresolved external symbol "private: int __thiscall Account::getNextAccountNumber(void)const " (?getNextAccountNumber#Account##ABEHXZ) referenced in function "public: __thiscall Account::Account(class std::basic_string,class std::allocator >,double)" (??0Account##QAE#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##N#Z) H:\programming\AccountClass\AccountClass.obj AccountClass
H:\programming\AccountClass\Debug\AccountClass.exe : fatal error LNK1120: 1 unresolved externals
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <string>
#include "Account.h"
using namespace std;
int main()
{
Account acct01;
Account acct02("Harold M. Ferguson", 2000);
Account acct03("Elise Janet Simmons", 3500);
Account acct04("James Holder", 0);
cout << endl << "Account information - initial" << endl;
acct01.displayAccountInfo(); // show account information - initial values
acct02.displayAccountInfo();
acct03.displayAccountInfo();
acct04.displayAccountInfo();
acct01.setAccountHolder("Mary A. Tarleton");
acct01.setBalance(542.39);
acct04.setAccountHolder("James Ellis Holder");
acct04.setBalance(1990.75);
cout << endl << "Account information after changes" << endl;
acct01.displayAccountInfo(); // show account information after changes
acct02.displayAccountInfo();
acct03.displayAccountInfo();
acct04.displayAccountInfo();
acct01.depositAmount(455); // make deposits
acct02.depositAmount(-19.95); // negative deposit not allowed - set to zero
acct03.depositAmount(4365.27);
acct04.depositAmount(95.63);
cout << endl << "Account information after deposits" << endl;
acct01.displayAccountInfo(); // show account information after deposits
acct02.displayAccountInfo();
acct03.displayAccountInfo();
acct04.displayAccountInfo();
acct01.withdrawAmount(37.39);
acct02.withdrawAmount(-475.25); // withdrawal may be positive or negative (absolute value)
acct03.withdrawAmount(0.25);
acct04.withdrawAmount(50.00);
cout << endl << "Account information after withdrawals" << endl;
acct01.displayAccountInfo(); // show account information after withdrawals
acct02.displayAccountInfo();
acct03.displayAccountInfo();
acct04.displayAccountInfo();
cout << endl;
system("pause");
return 0;
}
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include "Account.h"
#include <string>
using namespace std;
Account::Account()
{
accountID = getNextAccountNumber();
accountHolder = "no name";
balance = 0;
}
Account::Account(string name, double amount)
{
accountID = getNextAccountNumber();
accountHolder = name;
balance = amount;
}
int Account::getAccountID() const
{
return accountID;
}
string Account::getAccountHolder() const
{
return accountHolder;
}
double Account::getBalance() const
{
return balance;
}
void Account::setAccountHolder(string name)
{
accountHolder = name;
}
void Account::setBalance(double amt)
{
amt = balance;
}
void Account::depositAmount(double amt)
{
if (amt > 0)
{
balance = +amt;
}
else;
{
balance = balance;
}
}
void Account::withdrawAmount(double amt)
{
balance = balance - amt;
}
void Account::displayAccountInfo() const
{
cout << accountID << accountHolder << balance;
}
#ifndef ACCOUNT_H
#define ACCOUNT_H
#include <string>
using namespace std;
static int accountNumber = 100000; // starting value for account#
class Account
{
public:
Account(); // default constructor
Account(string name, double amount); // constructor with two parameters
int getAccountID() const; // ACCESSOR member functions
string getAccountHolder() const; // return name of account holder
double getBalance() const; // return account balance
void setAccountHolder(string name); // MUTATOR member functions
void setBalance(double amt); // assign amount to balance
void depositAmount(double amt); // add amount to balance
void withdrawAmount(double amt); // subtract absolute value of amount from balance
// HELPER member functions
void displayAccountInfo() const; // display account information
private:
int getNextAccountNumber() const; // get next account# (pre-increment account number)
// private DATA members
int accountID; // account# identifier
string accountHolder; // name of account holder
double balance; // account balance
};
// accountID = ++accountNumber
#endif
This problem is not related to the function being private - it is being called by the constructor(s), which have access to the private members of the class.
Both #DrewDormann and #PaulMcKenzie seem correct in the comments - you have (at least listed) no implementation for Account::getNextAccountNumber()
This should likely be in the second code snippet you have posted (likely Account.cpp, or similar)
Consider adding something like
int Account::getNextAccountNumber()
{
return accountNumber++;
}
However, this would seem in nature to be a function independent of anything even remotely related to any individual given Account, so consider making it a freestanding function. (i.e. not a member of the Account class)
Then you'd just have
int getNextAccountNumber()
{
return accountNumber++;
}
but in that case, you'd have to modify the header (perhaps Account.h?) to remove the member function. Otherwise, you'll still get the linker error you're currently hitting.
Edit: The function is declared as const, so you need the const specifier.
int Account::getNextAccountNumber() const
{
return accountNumber++;
}
I am following tutorials from youtube. It seems I have encountered an error I can't resolve by myself. The goal is to create a class called BMI, which takes users weight name and height and prints them out..
I'm trying to compile it using g++, and I suspect I'm not doing it right. Usually I just do g++ filename.cpp, as I should in this case?
The tutorial is originally in that Microsoft ....thing, I don't know it's name. Sorry
Thank you, the code is attached below.
The error
/tmp/ccRcewk3.o: In function `main':
Main.cpp:(.text+0x7d): undefined reference to `BMI::BMI()'
Main.cpp:(.text+0x89): undefined reference to `BMI::getWeight() const'
Main.cpp:(.text+0x9a): undefined reference to `BMI::getHeight() const'
Main.cpp:(.text+0xaf): undefined reference to `BMI::getName() const'
Main.cpp:(.text+0x14f): undefined reference to `BMI::~BMI()'
Main.cpp:(.text+0x184): undefined reference to `BMI::~BMI()'
collect2: ld returned 1 exit status
Main.cpp
#include <iostream>
#include <string>
#include "BMI.h"
using namespace std;
/**************************************************/
int main()
{
string name;
int height;
double weight;
cout << "Enter your name: ";
cin >> name;
cout << "Enter your height (cm): ";
cin >> height;
cout << "Enter your weight (kg): ";
cin >> weight;
BMI Student_1;
cout << endl << "Patient name: " << Student_1.getName() << endl <<
"Height: " << Student_1.getHeight() << endl <<
"Weight: " << Student_1.getWeight() << endl;
return 0;
}
/**************************************************/
BMI.h
// Header ==> Function Declarations
#include <iostream>
#include <string>
using namespace std;
// tu ide klasa
#ifndef BMI_H
#define BMI_H
class BMI
{
public:
//Default Constructor
BMI();
//Overload Constructor
BMI(string, int, double);
//Destructor
~BMI();
// Accessor functions
string getName() const;
// // // returns name of patient
int getHeight() const;
// // // returns height of patient
double getWeight() const;
// // // returns weight of patient
private:
// member variables
string newName;
int newHeight;
double newWeight;
};
#endif
BMI.cpp:
//Function definitions
#include "BMI.h"
// to access function inside a class
BMI::BMI()
{
newHeight = 0;
newWeight = 0.0;
}
BMI::BMI(string name, int height, double weight)
{
newName = name;
newHeight = height;
newWeight = weight;
}
BMI::~BMI()
{
}
string BMI::getName() const
{
return newName;
}
int BMI::getHeight() const
{
return newHeight;
}
int BMI::getWeight() const
{
return newWeight;
}
edit:
OK, thanks everyone, I got part of the problem solved. However, you got me a little confused with editing, so I will do over.
It seems that the original code is not working, and I feel it should. Anyway, the edited code from the question doesn't work either.
So, I will try to do it again. But thank you, now I know how to compile. :)
edit2:
Everything is working now, thank you very much.
You need to compile the main.cpp into Main.o and BMI.cpp into BMI.o.
g++ -c Main.cpp
g++ -c BMI.cpp
Then you need to link both object files into one executable (and link to the Standard C++ lib)
g++ -o myprog Main.o BMI.o -lstdc++
Run the example with
./myprog
There seem to be more bugs, I have no time to fix, please continue yourself. :-)
[marc#quadfork ~/test]$./myprog
Enter your name: foo
Enter your height (cm): 23
Enter your weight (kg): 2
Patient name:
Height: 0
Weight: 0
your function return noting in your BMI.cpp
try with this.
string BMI::getName() const
{
return newName;
}
int BMI::getHeight() const
{
return newHeight;
}
double BMI::getWeight() const
{
return newWeight;
}