Thread: Determine derived class type and manipulate it's member function

  1. #1
    Registered User
    Join Date
    Jan 2006
    Posts
    49

    Determine derived class type and manipulate it's member function

    I have a homework question. My problem is...

    Develop a polymorphic banking program using the Account hierarchy created in Exercise 12.10. Create a vector of Account pointers to SavingsAccount and CheckingAccount objects. For each Account in the vector, allow the user to specify an amount of money to withdraw from the Account using member function debit and an amount of money to deposit into the Account using member function credit. As you process each Account, determine its type. If an Account is a SavingsAccount, calculate the amount of interest owed to the Account using member function calculateInterest, then add the interest to the account balance using member function credit. After processing an Account, print the updated account balance obtained by invoking base class member function getBalance

    I have created classes and their member functions.

    Code:
    #include <iostream>
    using namespace std;
    
    
    class Account{
          public:
                 Account( double );
                 void credit( double );
                 void debt( double );
                 double getBalance();
          private:
                  double accountBalance;
    };
    
    
    class SavingsAccount: public Account{
          public:
                 SavingsAccount( double, double );
                 double calculateInterest();
          private:
                  double interestRate;
    };
    
    
    class CheckingAccount: public Account{
          public:
                 CheckingAccount( double, double );
                 void credit( double );
                 void debt( double );
          private:
                  double fee;
    };
    
    
    
    
    
    Account::Account( double initialbalance ){
                      if( initialbalance < 0 ){
                          accountBalance = 0;
                          cout << "Invalid entry, account balance is $0.00." << endl;
                      }
                      
                      else
                          accountBalance = initialbalance;
    }
    
    
    void Account::credit( double creditamount ){
         if( creditamount < 0 )
             cout << "Credit amount is less than $0.00, account has not been credited." << endl;
                      
         else
             accountBalance += creditamount;
    }
    
    
    void Account::debt( double debtamount ){
         if( ( accountBalance - debtamount ) < 0 )
             cout << "Debt amount exceed account balance, account has not been debited." << endl;
         
         else
             accountBalance -= debtamount;
    }
    
    
    double Account::getBalance(){
           return accountBalance;
    }
    
    
    SavingsAccount::SavingsAccount( double initialbalance, double interest ) : Account( initialbalance ){
                                    if( interest < 0 ){
                                        interestRate = 0;
                                        cout << "Invalid entry, account interest rate is 0%." << endl;
                                    }
                      
                                    else
                                        interestRate = interest;
    }
    
    
    double SavingsAccount::calculateInterest(){
           return getBalance() * ( interestRate / 100 );
    }
    
    
    CheckingAccount::CheckingAccount( double initialbalance, double transfee ) : Account( initialbalance ){
                                      if( transfee < 0 ){
                                        fee = 0;
                                        cout << "Invalid entry, account transaction fee is $0.00." << endl;
                                      }
                      
                                      else
                                          fee = transfee;
    }
    
    
    void CheckingAccount::credit( double deposit ){
         
         if( ( getBalance() + deposit - fee ) < 0 )// Makes sure fee doesn't drop account balance below $0.00
           cout << "Transaction would bring account below $0.00. Transaction not performed." << endl;
        
         else{
             Account::credit( deposit ); // Uses Account credit() to credit account
             Account::debt( fee );
         }
    }
         
    
    void CheckingAccount::debt( double withdrawl ){
         
         if( ( getBalance() - withdrawl - fee ) < 0 )// Makes sure fee doesn't drop account balance below $0.00
           cout << "Transaction would bring account below $0.00. Transaction not performed." << endl;
        
         else
             Account::debt( withdrawl + fee ); // Uses Account debt() to debit account
    }

    I can create the array of pointers and manipulate the member functions of the derived class by doing this....


    Code:
    for(int i=0; i<8; i++){
                if(i % 2 == 0)
                    accounts[i] = new SavingsAccount(0, 2);
                else
                    accounts[i] = new CheckingAccount(0, 3);
        }
        
    
        accounts[0]->credit(200);
        accounts[0]->debt(100);
        cout << accounts[0]->getBalance();
    
        
        
        
        for(int i=0; i<8; i++)
                delete accounts[i];

    What I don't know how to do it determine the class type and how to manipulate the calculateInterest function. How do I determine the type of the derived class and how do I manipulate the member functions of the derived classes?

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    What I don't know how to do it determine the class type and how to manipulate the calculateInterest function. How do I determine the type of the derived class and how do I manipulate the member functions of the derived classes?
    Use a dynamic_cast to try and convert the stored Account pointer to one of the other pointer types (either a SavingsAccount or a CheckingAccount pointer). If the cast fails (returns NULL) then the pointer is to an object of the other type; if it succeeds, then it is a pointer to that type.

    Code:
    if( dynamic_cast<SavingsAccount*>(accounts[0]) == NULL )
    {
        // accounts[0] is not a SavingsAccount pointer
    }
    else
    {
        // accounts[0] is a SavingsAccount pointer
    }
    You may need to enable RTTI in your settings when building the project in order to use the dynamic_cast. The base object should be a polymorphic type which means (I believe) that it must contain a virtual function.



    A couple nits:
    allow the user to specify an amount of money to withdraw from the Account using member function debit
    You're using a debt function everywhere in your code.



    Create a vector of Account pointers to SavingsAccount and CheckingAccount objects
    Does this mean a true STL vector container or is it simply saying to use an array. I mention this because I don't see you including the vector header.
    Last edited by hk_mp5kpdw; 04-27-2006 at 07:20 AM.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    Jan 2006
    Posts
    49
    hk_mp5kpdw

    Thank you for your reply. When I was given the homework assignment I was told not to use vector (we haven't covered that yet). The debt/debit difference is because the previous homework assignment (problem 12.10) asked for a debt member function.

    I tried the dynamic_cast but it didn't work, I got this message...

    cannot dynamic_cast `accounts[0]' (of type `class Account*') to type `class SavingsAccount*' (source type is not polymorphic)

    Actually, I think I've developed a work around for it. What I really need is to be able to call the member functions of the derived class. When I try to call calculateInterest() by doing this...

    Code:
    cout << accounts[0]->calculateInterest();
    I get an error that says: 'class Account' has no member named 'calculateInterest'.

  4. #4
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Quote Originally Posted by rakan
    hk_mp5kpdw
    I tried the dynamic_cast but it didn't work, I got this message...

    cannot dynamic_cast `accounts[0]' (of type `class Account*') to type `class SavingsAccount*' (source type is not polymorphic)
    Quote Originally Posted by hk_mp5kpdw
    You may need to enable RTTI in your settings when building the project in order to use the dynamic_cast. The base object should be a polymorphic type which means (I believe) that it must contain a virtual function.
    As you have written it, the base class does not contain any virtual functions. A class designed as a base class (something to derive from) should always include at least a destructor that is defined as being virtual.




    Quote Originally Posted by rakan
    Actually, I think I've developed a work around for it. What I really need is to be able to call the member functions of the derived class. When I try to call calculateInterest() by doing this...

    Code:
    cout << accounts[0]->calculateInterest();
    I get an error that says: 'class Account' has no member named 'calculateInterest'.
    You would need to create a virtual function in the base Account class that you override in at least the SavingsAcount derived class. The base version doesn't have to do anything. However, this appears to skip the "determine its type" part of the requirement if you blindly call the function.
    Last edited by hk_mp5kpdw; 04-27-2006 at 07:55 AM.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  5. #5
    Registered User
    Join Date
    Jan 2006
    Posts
    49
    Ooooo! Now I see. I got it to work! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you!

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    BTW, this program does not use polymorphism. The homework instructions that say, "As you process each Account, determine its type," are telling you to use poor design. The entire point of polymorphism is to avoid having to know the derived type of the object. All you have to do is call a virtual function from the base class pointer and the virtual mechanism will make sure the correct derived class code will be executed.

    So a better design would be to make debit and credit virtual. Then, in the SavingsAccount override of credit, the calculateInterest part could be used to add the interest. That way you never have to actually determine the type as a SavingsAccount, and the code that uses the Accounts can stay generic.

    Hopefully either the homework was poorly worded and you misunderstood about the need for the dynamic_cast, or this homework will be used to show how not to do things later on. If not, then you are learning the wrong way to use polymorphism.

  7. #7
    Registered User
    Join Date
    Jan 2006
    Posts
    49
    Daved,

    Thank you for the advice. I see what you mean. As I was writing the code I did realize that I had to make the base class member functions virtual. The dynamic_cast may not be necessary. I think I have to ask my professor what they mean by "As you process each Account, determine its type". That does sound contrary to the purpose of polymorphism.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. I need the code of few programs in c++.plzzzzz help...plzzz
    By NAVINKR20 in forum C++ Programming
    Replies: 1
    Last Post: 05-08-2009, 09:13 AM
  2. Help with FIFO QUEUE
    By jackfraust in forum C++ Programming
    Replies: 23
    Last Post: 04-03-2009, 08:17 AM
  3. Need help with FIFO Queue using Singly Linked Lists
    By astou in forum C++ Programming
    Replies: 6
    Last Post: 03-15-2008, 02:36 PM
  4. Smart pointer class
    By Elysia in forum C++ Programming
    Replies: 63
    Last Post: 11-03-2007, 07:05 AM
  5. include question
    By Wanted420 in forum C++ Programming
    Replies: 8
    Last Post: 10-17-2003, 03:49 AM