Problems understanding virtual functions...

Pages: 12
I'm having trouble with an assignment I'm doing where we have to design a bank system with quite a few classes and derived classes. The problem is that I don't quite understand how the "virtual" keyword works. I made sure to declare any pure virtual functions in the derived class and to inherit publicly. But when I try to create an instance of the derived class, it tells me that I can't instantiate an object of an abstract class... but I did everything by the book, so I don't understand what's wrong.

The abstract base class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class bankAccount
{
	public:
		bankAccount();
		bankAccount(int acct, string acct_name, double acct_balance);
		virtual ~bankAccount();

		virtual string getName(void) = 0;
		virtual int getAcctNum(void) = 0;
		virtual double getBalance(void) = 0;

		void makeDeposit(double amnt);
		void withdrawMoney(double amnt);
		virtual void monthlyStatement(void) const = 0;
	protected:
		int acct_num;
		string name;
		double balance;
};


The functions for the abstract base class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
bankAccount::bankAccount()
{
	acct_num = 0;
	name = "Default";
	balance = 0.00;
}
bankAccount::bankAccount(int acct, string acct_name, double acct_balance)
{
	acct_num = acct;
	name = acct_name;
	balance = acct_balance;
}
bankAccount::~bankAccount()
{

}

void bankAccount::makeDeposit(double amnt)
{
	balance += amnt;
	cout << "$" << amnt << " deposited into account." << std::endl;
}
void bankAccount::withdrawMoney(double amnt)
{
	if(balance >= amnt)
	{
		balance -= amnt;
		cout << "$" << amnt << " withdrawn from account." << std::endl;
	}
	else
	{
		cout << "Insufficient funds for transaction." << std::endl;
	}
}


The derived class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class checkingAccount: public bankAccount
{
	public:
		checkingAccount();
		checkingAccount(int acct_num, string acct_name, double acct_balance);
		~checkingAccount();

		string getName(void);
		int getAcctNum(void);
		double getBalance(void);

		void monthlyStatement(void);
	private:
};


The derived class functions:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
checkingAccount::checkingAccount()
{

}
checkingAccount::checkingAccount(int acct_num, string acct_name, double acct_balance)
{
	bankAccount(acct_num, acct_name, acct_balance);
}
checkingAccount::~checkingAccount()
{

}

string checkingAccount::getName()
{
	return name;
}
int checkingAccount::getAcctNum()
{
	return acct_num;
}
double checkingAccount::getBalance()
{
	return balance;
}

void checkingAccount::monthlyStatement()
{

}


And finally, the line that tries to create an instance of the derived class:
 
bankAccount *checking = new checkingAccount(acct, acct_name, acct_balance);


What am I doing wrong? Virtual functions are so confusing...
You have to declare the methods of the derived class as virtual too.
But the tutorial on CPlusPlus.com showed an example where the base class' functions were declared like:

 
virtual void foo() = 0;


And the derived class' function was derived like:

 
void foo();
Sorry about that, that works just fine.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A
{
	public:
	virtual void lol() = 0;
};

class B : public A
{
	public:
	void lol()
	{
		std::cout<<"lol";
	}
};

A* a = new B;
	a->lol(); 


This works completely well for me. Mind trying to compile that?


EDIT: Just saw your problem:

1
2
3
4
checkingAccount::checkingAccount(int acct_num, string acct_name, double acct_balance)
{
	bankAccount(acct_num, acct_name, acct_balance);
}


should be

1
2
3
checkingAccount::checkingAccount(int acct_num, string acct_name, double acct_balance)
   :	bankAccount(acct_num, acct_name, acct_balance)
{}
Last edited on
Just to clarify, my class is in a header file and functions are in a CPP file separate from the main CPP file. Does that matter?

Also, I'm using Visual Studio 2010 Ultimate.
Last edited on
Look at my edit.

EDIT: forget it, you just can't create instances of classes with pure virtuals, not even in the initialization list.
Last edited on
It's still saying that checkingAccount is an abstract class...
No, checkingAccount is no abstract class, but it tried to create an instance of an abstract class in it's constructor. Sorry, you can't create it in the initialization list either.
I don't understand... I changed my code to look like yours...
The assignment says "some of these functions will be pure virtual" for the bankAccount class. If I can't create instances of a class with pure virtual functions, how do I implement this? There are other subclasses of checkingAccount as well.
If what you say is true, then that code you gave me to test up above shouldn't have worked. It worked.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A
{
	public:
	A(int,int,int){};
	virtual void lol() = 0;
};

class B : public A
{
	public:
	B() : A(1,2,3) {}
	void lol()
	{
		std::cout<<"lol";
	}
};


This works, so I don't quite get your problem.
It's compiling fine when I test similar things in the same file... so I have to assume the problem is that I'm using external CPP files and header files.
Nah it's not.
Maybe it's a problem with the way I linked the files together? Take a look at the entire program.

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* Project: CIS 225 Chapter 14 - Programming Exercise #5
* Author: packetpirate
* Last Updated: 03/26/2011
**/

#include <iostream>
using std::cout;
#include "bank_account.h"
#include "certificate_of_deposit.h"
#include "checking_account.h"
#include "high_interest_checking.h"
#include "high_interest_savings.h"
#include "no_service_charge_checking.h"
#include "savings_account.h"
#include "service_charge_checking.h"

int main(int argc, char** argv)
{
	int acct = 5467;
	string acct_name = "Person";
	double acct_balance = 5.00;

	bankAccount *checking = new checkingAccount(acct, acct_name, acct_balance);

	cout << "Checking Balance: " << checking->getBalance() << std::endl;
	checking->makeDeposit(20.00);
	cout << "Checking Balance: " << checking->getBalance() << std::endl;

	delete checking;

	return 0;
}


bank_account.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#ifndef BANK_ACCOUNT_H
#define BANK_ACCOUNT_H

/**
* File - bank_account.h
* Usage - Definition of bankAccount class.
* Last Updated - 03/26/2011
**/

#include <string>
using std::string;

class bankAccount
{
	public:
		bankAccount();
		bankAccount(int acct, string acct_name, double acct_balance);
		virtual ~bankAccount();

		virtual string getName() = 0;
		virtual int getAcctNum() = 0;
		virtual double getBalance() = 0;

		void makeDeposit(double amnt);
		void withdrawMoney(double amnt);
		virtual void monthlyStatement() const = 0;
	protected:
		int acct_num;
		string name;
		double balance;
};

#endif BANK_ACCOUNT_H 


bank_account.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* File - bank_account.cpp
* Usage - Class bankAccount's function definitions.
* Last Updated - 03/26/2011
**/

#include <iostream>
using std::cout;
#include <string>
using std::string;
#include "bank_account.h"

bankAccount::bankAccount()
{
	acct_num = 0;
	name = "Default";
	balance = 0.00;
}
bankAccount::bankAccount(int acct, string acct_name, double acct_balance)
{
	acct_num = acct;
	name = acct_name;
	balance = acct_balance;
}
bankAccount::~bankAccount()
{

}

void bankAccount::makeDeposit(double amnt)
{
	balance += amnt;
	cout << "$" << amnt << " deposited into account." << std::endl;
}
void bankAccount::withdrawMoney(double amnt)
{
	if(balance >= amnt)
	{
		balance -= amnt;
		cout << "$" << amnt << " withdrawn from account." << std::endl;
	}
	else
	{
		cout << "Insufficient funds for transaction." << std::endl;
	}
}


checking_account.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef CHECKING_ACCOUNT_H
#define CHECKING_ACCOUNT_H

/**
* File - checking_account.h
* Usage - Definition of checkingAccount class.
* Last Updated - 03/26/2011
**/

#include <string>
using std::string;
#include "bank_account.h"

class checkingAccount: public bankAccount
{
	public:
		checkingAccount();
		checkingAccount(int acct, string acct_name, double acct_balance);
		~checkingAccount();

		string getName();
		int getAcctNum();
		double getBalance();

		void monthlyStatement();
};

#endif CHECKING_ACCOUNT_H 


checking_account.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* File - checking_account.cpp
* Usage - Class checkingAccount's function definitions.
* Last Updated - 03/26/2011
**/

#include "checking_account.h"

checkingAccount::checkingAccount()
{

}
checkingAccount::checkingAccount(int acct, string acct_name, double acct_balance): bankAccount(acct, acct_name, acct_balance)
{

}
checkingAccount::~checkingAccount()
{

}

string checkingAccount::getName()
{
	return name;
}
int checkingAccount::getAcctNum()
{
	return acct_num;
}
double checkingAccount::getBalance()
{
	return balance;
}

void checkingAccount::monthlyStatement()
{

}
Header files shouldn't have global using statements and you shouldn't have any using statements in front of any headers. Your #endif directives shouldn't have anything following them.

And you forgot a const in your checkingAccount::monthlyStatement() function. monthlyStatement() and monthlyStatement() const are two different functions.
Not sure if it helps. I see the default constructor of checkingAccount is not calling the default constructor bankAccount. Maybe this is done automatically by C++? I don't know if it does because I usually am 100% explicit about this type of thing. I would have written:

1
2
checkingAccount::checkingAccount() : bankAccount()
{ }
I corrected everything except the global #includes in the headers. Why shouldn't they be? I do it all the time and have never gotten an error because of it.

Even after the corrections suggested, I'm getting the same error.

Even after the corrections suggested, I'm getting the same error.


You haven't corrected monthlyStatement in your checkingAccount. I compiled your project just fine with that one change.

Anyways, #includes are no problem, I said not to use using's in your headers/before your headers.
EDIT: Whoops, corrected it in the wrong file.
Last edited on
Pages: 12