Pointer to a Base Class through a Derived Class

First off: I'm not exactly sure if the title of this topic is correct, but quite frankly I'm lost on this problem!

Ok, my problem is I am trying to make a vector array of pointers to a base class, that all of my derived classes have in common. I'm unsure as to how to do such a thing.

Here is a summary of the code:

AbstractAccount (The 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
#ifndef ABSTRACT_ACCOUNT_H
#define ABSTRACT_ACCOUNT_H

#include <string>

class AbstractAccount 
{
	public:
       
       AbstractAccount(const std::string& accNum,  int cents, bool enabled = true) ;
       virtual ~AbstractAccount();
       std::string getAccountNumber() const;
       int getAmountInCents() const ;
       bool enable();
       bool disable(); 
       virtual bool withdraw(int cents) = 0;
       virtual bool deposit(int cents) = 0;
             
	protected:
          std::string accountNumber ;
          int amountInCents ;
          bool accountEnabled ;
};

#endif // ABSTRACT_ACCOUNT_H 


SavingsAccount (a derived 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
35
36
37
38
#ifndef SAVINGSACCOUNT_H_
#define SAVINGSACCOUNT_H_

#include "AbstractAccount.h"
#include "SimpleBankingApplication.h"
#include <iostream>

#define INTEREST_RATE 1.01

using namespace std;

extern unsigned int largestNameLength;
extern unsigned int numberOfSpaces;

class SavingsAccount: protected AbstractAccount
{
	public:
		SavingsAccount(const std::string& accNum,  double amount, bool enabled):
			AbstractAccount(accNum, int(amount*100.00), enabled){interestRate = INTEREST_RATE;}
		
		~SavingsAccount();
		
		double getInterestRate();
		bool setInterestRate(double rate);
		bool payInterest();
		
		bool withdraw(int cents);
		bool deposit(int cents);
		
		friend istream &operator>>(istream& inStream, SavingsAccount &accountToInput);
		friend ostream &operator<<(ostream& outStream, const SavingsAccount accountToPrint);
	
	protected:
		double interestRate;

};

#endif /*SAVINGSACCOUNT_H_*/ 


SimpleBankingApplication (A class involving the vector of AbstractAccount pointers):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef SIMPLE_BANKING_APPLICATION_H
#define SIMPLE_BANKING_APPLICATION_H

#include "AbstractAccount.h"
#include <vector>
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <string>

class SimpleBankingApplication 
{
    std::vector<AbstractAccount *> accountList;
      
    public:
       SimpleBankingApplication();
       ~SimpleBankingApplication();
       void createAccounts(const std::string& accountFileName);
       
    private:
        
};

#endif // SIMPLE_BANKING_APPLICATION_H 


In the "SimpleBankingApplication.cpp" file, I've tried to implement the following:

1
2
3
4
5
AbstractAccount* abstractAccountPointer;

abstractAccountPointer = new (AbstractAccount) SavingsAccount("", 0, true);

accountList.push_back(abstractAccountPointer);
The compiler error I get is
`AbstractAccount' is an inaccessible base of `SavingsAccount'
Thanks for any help!
Will doing it like this work?

abstractAccountPointer = (AbstractAccount*) (new SavingsAccount("", 0, true));
Last edited on
I may be missing something but I don't see why this shouldn't work:

1
2
3
abstractAccountPointer = new SavingsAccount("", 0, true);

accountList.push_back(abstractAccountPointer);
@Galik
Yeah, ok, that's fine too. I just did the casting explicitly coz that's what he intended to do in the frist place.
Upcasting to a base class type does not require an explicit cast.
Thanks for your replies.

I changed the type of inheritance the SavingsAccount had from protected to public, and it let up on the error... but now after I try to dereference the account that I've pushed into the vector, I get a memory address and not the object. What am I doing wrong here?

Here is what I have changed from my previous code:

SavingsAccount.h:
class SavingsAccount: public AbstractAccount

SimpleBankingApplication (assume that the IO file stream is set up correctly):
1
2
3
4
5
6
7
8
9
10
11
12
13
SavingsAccount inSavingsAccount("", 0, true);

AbstractAccount *abstractAccountPointer;
			
abstractAccountPointer = new SavingsAccount("", 0, true);
			
fileIn >> inSavingsAccount;
			
abstractAccountPointer = &inSavingsAccount;
			
accountList.push_back(abstractAccountPointer);	

cout << accountList[0] << endl;


jsmith wrote:
Upcasting to a base class type does not require an explicit cast.
What you wanted to say is:
Downcasting to a base class type does not require an explicit cast.

Yes, ok, it's not required to be done explicitly.

matttheuCman wrote:
I changed the type of inheritance the SavingsAccount had from protected to public, and it let up on the error...
Ok

matttheuCman wrote:
but now after I try to dereference the account that I've pushed into the vector, I get a memory address and not the object. What am I doing wrong here?
But that's what your accountList is! You declare it as a vector of pointers to AbstractAccount. Maybe declaring a virtual function show() could be a solution to your problem. You could call it like:
1
2
for (int i=0; i<accountList.size(); i++)
     accountList[i]->show();

Also modify your input procedure like this:
1
2
3
SavingsAccount * inSavingsAccount = new SavingsAccount("", 0, true);
fileIn >> *inSavingsAccount;
accountList.push_back(inSavingsAccount);

You see there is a memory leak in the current one, right here:
1
2
3
abstractAccountPointer = new SavingsAccount("", 0, true);
//...
abstractAccountPointer = &inSavingsAccount;

Also, inSavingsAccount (the way you declare it) is a temporary variable and you store its address on a vector... Maybe when you decide to use it it won't exist...
Last edited on
Downcasting


Actually it is called upcasting usually:

base

cast up
|
derived
Indeed... my bad... sorry...
So I guess if I wanted my vector of AbstractAccount pointers to point to objects instead of the memory location of the object, I need to make a separate vector for each object type? I cannot change the .h files of the SimpleBankingApplication or the AbstractAccount... but I want to be able to store objects into the vector. How would this be done?
It's a good idea you declare the vector as a container of pointers to AbstractAccount because this way you can also hold pointers of classes derived from AbstractAccount (this is called upcasting), which as I understand is something that you want to do.

I cannot change the .h files of the SimpleBankingApplication or the AbstractAccount...
Why is that?...

but I want to be able to store objects into the vector. How would this be done?
Holding addresses of objects is fine as well, it's just more tricky to handle. When you choose to go this way you must make sure that the address you store on a vector always points at something good every time you use it.

In your example you stored the address of a local variable in the vector and that could cause a problem. I realized that this wasn't really your intention and that you actually wanted to store the address of the newly dynamically allocated variable but, well you didn't do that... After the corrections I suggested it should work fine! Just remember to delete these things when you're done with them.

EDIT: accountList[i] returns a pointer to a base class object (AbstractAccount*) but you don't know if this is actually a derived object... Well, ok, you know it is because you made AbstractAccount pure virtual (which means you can't have instantiated objects of this type) and SavingsAccount is the only class derived from AbstractAccount. But what if you also had another class derived from AbstractAccount?... How would you know if it was a SavingsAccount or the other, since what you only have is a pointer to an AbstractAccount?... The answer is virtual functions! I gather you are familiar with them but I wanted you to see that this solution can't be used (directly) with these functions:

1
2
friend istream & operator>>(istream& inStream, SavingsAccount &accountToInput);
friend ostream & operator<<(ostream& outStream, const SavingsAccount accountToPrint);

as these functions are not memeber functions... What you can do though is declare & define a virtual function show() for your account classes and then do something like this:

1
2
3
4
5
//in your base class:
friend istream & operator>>(istream & inStream, AbstractAccount & accountToInput)
{accountToInput.show();}
friend ostream & operator<<(ostream & outStream, const AbstractAccount & accountToPrint)
{accountToPrint.show();}

1
2
3
//in your derived class:
friend ostream & operator<<(ostream& outStream, const SavingsAccount & accountToPrint)
{accountToPrint.show();}

Then you can use it like cout << *(accountList[i]) << endl;

EDIT: I reworked a bit the solution I suggested with show() and ostream, fixed a huge typo hahaha and add the following:

You can also do something like the above for input! Declare & define a virtual function set() that handles input of accounts and then add the following lines:

1
2
3
//in your base class:
friend istream & operator>>(istream & inStream, AbstractAccount & accountToInput)
{accountToInput.set();}

1
2
3
//in your derived class:
friend istream & operator>>(istream & inStream, SavingsAccount & accountToInput)
{accountToInput.set();}

Then you can use operator >> for input without caring whether the target object is a base or derived one.
Last edited on
Topic archived. No new replies allowed.