I recently completed a program and want to break up the classes into header files and cpp files. I've got the declarations in the header files, but I can't get it to build if I try to move the implementation of the classes to separate cpp files. I know you can move the implementation to a cpp and call it, but I can't figure out how to make it work. BTW, I haven't had too much experience with classes so that's why I'm a little lost. Anyway, I'm asking for some help to sort out the problem.

Transaction Header

#ifndef Transaction_h
#define Transaction_h

class Transaction
{
	public:
		Transaction();
		Transaction(float InAmount, char InCode, char InNote[]);             

		void SetAmount(float NewAmount);
		float GetAmount();
		void SetCode(char NewCode);
		char GetCode();
		void SetNote(char* NewNote);
		const char*	GetNote();

	private:
		float Amount;	//Transaction amount
		char Code;		//Transaction type, 'D' for deposit, 'W' for withdrawal
		char Note[20];	//Transaction note
};

#endif

BankStatement Header

#ifndef BankStatement_h
#define BankStatement_h

class BankStatement
{
	public:
		BankStatement();

		void	SetBegBal(float Balance);
		float	GetBegBal();
		float	GetEndBal();

		int		GetNumEntries();
		void	EnterTransaction(Transaction Input);
		void	DisplayResults();			//Displays BegBal, TransactionLog array,
											//RunningBal array, and final stats

		void	ArrangeTransactions();
		void	PrintArranged();

	private:
		Transaction		TransactionLog[MaxTransactions];
		Transaction		Arranged[MaxTransactions];

		int	NumEntries;
		float RunningBal[MaxTransactions];
		float BegBal;								//Beginning balance
		float EndBal;								//Balance of last transaction
};

#endif

Lab CPP

#include <iostream>
using std::cin;
using std::cout;
using std::endl;

#include <cstring>
using std::strcpy;

#include <math.h>
using namespace std;

const int MaxTransactions = 10;

#include "Transaction.h"
#include "BankStatement.h"

int main()
{
	BankStatement MyStatement;						//Create statement
	
	MyStatement.SetBegBal (15.92f);					//Beginning balance

//Declare various transactions
	Transaction T1;
	T1.SetAmount(123.56f);
	T1.SetCode('D');
	T1.SetNote("CTPay");

	Transaction T2(153.86f, 'W', "Rent");

	Transaction T3;
	T3.SetAmount(75.56f);
	T3.SetCode('D');
	T3.SetNote("Tips");

	Transaction T4(12.56f,'D',"Gift");

	Transaction T5;
	T5.SetAmount(73.74f);
	T5.SetCode('W');
	T5.SetNote("Date");

	Transaction T6(145.75f, 'D',"Loan");

	Transaction T7;
	T7.SetAmount(40.00f);
	T7.SetCode('W');
	T7.SetNote("Loan Payment");

	Transaction T8(21.74f, 'W', "Groceries");

//Inserting the objects into the bank statement
	MyStatement.EnterTransaction(T1);
	MyStatement.EnterTransaction(T2);
	MyStatement.EnterTransaction(T3);
	MyStatement.EnterTransaction(T4);
	MyStatement.EnterTransaction(T5);
	MyStatement.EnterTransaction(T6);
	MyStatement.EnterTransaction(T7);
	MyStatement.EnterTransaction(T8);

//View history
	MyStatement.DisplayResults();

	cout << endl;

//View grouped transactions
	MyStatement.ArrangeTransactions();
	MyStatement.PrintArranged();

	return 0;
}


Transaction::Transaction()
{
//Default field values
	Amount = 0.0f;
	Code = 'U'; // Unknown code
	strcpy(Note, ""); //No comment given
}

Transaction::Transaction(float InAmount, char InCode, char InNote[])
{
//Setup fields according to parameters passed to Constructor
	Amount = InAmount;
	Code = InCode;
	strcpy(Note, InNote);
}

void Transaction::SetAmount(float NewAmount)
{
	Amount = NewAmount;
}

float Transaction::GetAmount()
{
	return Amount;
}

void Transaction::SetCode(char NewCode)
{
	Code = NewCode;
}

char Transaction::GetCode()
{
	return Code;
}

void Transaction::SetNote(char* NewNote)
{
	strcpy(Note, NewNote);
}

const char* Transaction::GetNote()
{
	return Note;
}


BankStatement::BankStatement()
{
	NumEntries = 0;
	BegBal = EndBal = 0.0f;
}

void BankStatement::SetBegBal(float Balance)
{
//Before any transaction was performed, beginning and ending balances would be equal
	EndBal = BegBal = Balance;
	NumEntries = 0;
}

float BankStatement::GetBegBal()
{
	return BegBal;
}

float BankStatement::GetEndBal()
{
	return EndBal;
}

int BankStatement::GetNumEntries()
{
	return NumEntries;
}

void BankStatement::EnterTransaction(Transaction Input)
{

//Check if transactions count didn't reach max value
	if (NumEntries == MaxTransactions)
		return;


	TransactionLog[NumEntries] = Input;
	
	// update ending balance field according to transaction type
	if (Input.GetCode() == 'D') // deposit transaction
	{
		EndBal += Input.GetAmount();
	}
	else // withdraw transaction
	{
		EndBal -= Input.GetAmount();
	}

	// check for float precision issue
	if (fabs(EndBal) < 0.01) EndBal = 0;

	// copy current ending balance to running balance
	RunningBal[NumEntries] = EndBal;
	
	NumEntries++;
}

void BankStatement::DisplayResults()
{
	// setup output format (2 digits after decimal point)
	cout.setf(ios_base::fixed);
	cout.precision(2);

	// print balance details

	cout << "The beggining balance was: $" << BegBal << endl;
	
	int nDepNum = 0;
	for (int Count = 0; Count < NumEntries; Count++)
	{
		cout << "Transaction#" << Count + 1 << " was a " << TransactionLog[Count].GetCode() << " amount: $"
			<< Count[TransactionLog].GetAmount() << " for " << TransactionLog[Count].GetNote() << endl
			<< "Running balance: $" << RunningBal[Count];

		if (RunningBal[Count] < 0) cout << " OVERDRAWN";
		cout << endl;

		if (TransactionLog[Count].GetCode() == 'D') nDepNum++;
	}

	cout << "The ending balance is: $" << EndBal << endl << "The number of Transactions is: " << NumEntries << endl
		<< "The number of Deposits is: " << nDepNum << endl << "The number of Withdrawals is: "
		<< NumEntries - nDepNum << endl;
}

void BankStatement::ArrangeTransactions()
{	
	int ArrangedIndex = 0;

	for (int Count = 0; Count < NumEntries; Count++)
	{
		if (TransactionLog[Count].GetCode() != 'D') continue;
		Arranged[ArrangedIndex] = TransactionLog[Count];
		ArrangedIndex++;
	}

	for (int Count = 0; Count < NumEntries; Count++)
	{
		if (TransactionLog[Count].GetCode() != 'W') continue;
		Arranged[ArrangedIndex] = TransactionLog[Count];
		ArrangedIndex++;
	}
}

void BankStatement::PrintArranged()
{

// print arranged transactions array
	cout << "Printing the Deposits and Withdrawals as a group:" << endl;
	for (int Count = 0; Count < NumEntries; Count++)
	{
		cout << "Transaction#" << Count + 1 << " was a " << Arranged[Count].GetCode() << " amount: $"
			<< Arranged[Count].GetAmount() << " for " << Arranged[Count].GetNote() << endl;
	}
}

Recommended Answers

All 5 Replies

It compiled without error for me. What error message(s) did you get with your compiler. I used VC++ 2008 Express.

It compiled without error for me. What error message(s) did you get with your compiler. I used VC++ 2008 Express.

I don't think he meant that it had errors but that he couldn't build the files in separate .cpp files outside of a project.

My question to the original poster, did you try adding your .cpp files to a different project, or using --

#include "filename.h"

--for header files in your "default" directory?

I don't think you can run the files without a project, or at least I never can. I use Dev-cpp 4.9 and it's always been like that for me.

Yeah, how I posted it in the beginning compiles fine. I'm kinda referring to what Alex said, trying to separate the classes into two different .h and .cpp files. I wanted to put the different class implementation into their own .cpp files and compile that way. Like pull the following into their own files and leave main in the file alone. My instructor was saying to separate the class declarations from the actual implementation of the class. So, I want to have two .h files and three .cpp files.

Transaction::Transaction()
{
//Default field values
	Amount = 0.0f;
	Code = 'U'; // Unknown code
	strcpy(Note, ""); //No comment given
}

Transaction::Transaction(float InAmount, char InCode, char InNote[])
{
//Setup fields according to parameters passed to Constructor
	Amount = InAmount;
	Code = InCode;
	strcpy(Note, InNote);
}

void Transaction::SetAmount(float NewAmount)
{
	Amount = NewAmount;
}

float Transaction::GetAmount()
{
	return Amount;
}

void Transaction::SetCode(char NewCode)
{
	Code = NewCode;
}

char Transaction::GetCode()
{
	return Code;
}

void Transaction::SetNote(char* NewNote)
{
	strcpy(Note, NewNote);
}

const char* Transaction::GetNote()
{
	return Note;
}
BankStatement::BankStatement()
{
	NumEntries = 0;
	BegBal = EndBal = 0.0f;
}

void BankStatement::SetBegBal(float Balance)
{
//Before any transaction was performed, beginning and ending balances would be equal
	EndBal = BegBal = Balance;
	NumEntries = 0;
}

float BankStatement::GetBegBal()
{
	return BegBal;
}

float BankStatement::GetEndBal()
{
	return EndBal;
}

int BankStatement::GetNumEntries()
{
	return NumEntries;
}

void BankStatement::EnterTransaction(Transaction Input)
{

//Check if transactions count didn't reach max value
	if (NumEntries == MaxTransactions)
		return;


	TransactionLog[NumEntries] = Input;
	
	// update ending balance field according to transaction type
	if (Input.GetCode() == 'D') // deposit transaction
	{
		EndBal += Input.GetAmount();
	}
	else // withdraw transaction
	{
		EndBal -= Input.GetAmount();
	}

	// check for float precision issue
	if (fabs(EndBal) < 0.01) EndBal = 0;

	// copy current ending balance to running balance
	RunningBal[NumEntries] = EndBal;
	
	NumEntries++;
}

void BankStatement::DisplayResults()
{
	// setup output format (2 digits after decimal point)
	cout.setf(ios_base::fixed);
	cout.precision(2);

	// print balance details

	cout << "The beggining balance was: $" << BegBal << endl;
	
	int nDepNum = 0;
	for (int Count = 0; Count < NumEntries; Count++)
	{
		cout << "Transaction#" << Count + 1 << " was a " << TransactionLog[Count].GetCode() << " amount: $"
			<< Count[TransactionLog].GetAmount() << " for " << TransactionLog[Count].GetNote() << endl
			<< "Running balance: $" << RunningBal[Count];

		if (RunningBal[Count] < 0) cout << " OVERDRAWN";
		cout << endl;

		if (TransactionLog[Count].GetCode() == 'D') nDepNum++;
	}

	cout << "The ending balance is: $" << EndBal << endl << "The number of Transactions is: " << NumEntries << endl
		<< "The number of Deposits is: " << nDepNum << endl << "The number of Withdrawals is: "
		<< NumEntries - nDepNum << endl;
}

void BankStatement::ArrangeTransactions()
{	
	int ArrangedIndex = 0;

	for (int Count = 0; Count < NumEntries; Count++)
	{
		if (TransactionLog[Count].GetCode() != 'D') continue;
		Arranged[ArrangedIndex] = TransactionLog[Count];
		ArrangedIndex++;
	}

	for (int Count = 0; Count < NumEntries; Count++)
	{
		if (TransactionLog[Count].GetCode() != 'W') continue;
		Arranged[ArrangedIndex] = TransactionLog[Count];
		ArrangedIndex++;
	}
}

void BankStatement::PrintArranged()
{

// print arranged transactions array
	cout << "Printing the Deposits and Withdrawals as a group:" << endl;
	for (int Count = 0; Count < NumEntries; Count++)
	{
		cout << "Transaction#" << Count + 1 << " was a " << Arranged[Count].GetCode() << " amount: $"
			<< Arranged[Count].GetAmount() << " for " << Arranged[Count].GetNote() << endl;
	}
}

Try this--

Add all of your files (the .h ones included) to a project and be sure to mark each .h file with the preprocessor definition of pragma, like this--

#pragma once

so the file isn't included twice.

Notice that even though your header files are in the same folder/project that you will have to include them for each .cpp file in the project.

Kinda like this--

/**
Class 1
*/

#include "header1.h"
#include "header2.h"
/**
Class 2
*/

#include "header1.h"
#include "header2.h"
/**
header1.h
*/

#pragma once
/**
header2.h
*/

#pragma once

You'll notice that you wont need the .h files in your project, but instead in the "default" directory for whatever program you're using to build your projects.

What I'd suggest is to make a new project and add 2 new files to them, name them with the class names and copy and paste the data that you want in separate classes to those classes.

Afterwards make two more files but save them with the .h extension instead of the .cpp and copy and paste the information you want as header files in those files.

Once that's done, move them to the default directory (or leave them where they are) such that you can include both header files without having to directly place them in your project.

I hope that makes sense.

Metalsiege: you never did say what compiler you are using. Exactly how to do what you want depends on what compiler IDE you are using because each one is different. I used VC++ 2008, created a new project, then added each of the *.cpp and *.h files to the project. Compiles and links without errors that way.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.