Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Manipulating with pointers to derived class objects through pointers to base class objects

I have this code to represent bank:

class Bank {
    friend class InvestmentMethod;
    std::vector<BaseBankAccount*> accounts;
public:
//...

BaseBankAccount is an abstract class for all accounts in a bank:

class BaseBankAccount {
    public:
        BaseBankAccount() {}
        virtual int getInterest() const = 0;
        virtual int getInvestedSum() const = 0;
        virtual void increaseDepositSum(int additionalSum) = 0;
        virtual void close(std::string& reason) = 0;
        virtual ~BaseBankAccount() {}
};

The problem is, when I manipulate with pointers to derived class objects through pointers to base class objects, the set of methods I can call is restricted by BaseBankAccount public interface - no matter what type the REAL object is.

For example, not every account has an option to increase sum invested already - so, I didn`t include this method in a base class:

class BankAccount: public BaseBankAccount {
protected:
    BaseDeposit* deposit;
    double sumInvested;
public:
    BankAccount(int sum, int term, int inter): sumInvested(sum), depositTerm(term), interest(inter) {}
    int getInterest() const { return interest; }
    int getInvestedSum() const { return sumInvested; }
    void prolong(int increaseTerm) {
        depositTerm += increaseTerm;
    }
    void increaseInvestment(double addition) {
            sumInvested += addition;
    }
    virtual ~BankAccount() {}
};

then, I want to call it:

Bank bank1(...);
bank1.accounts[i]->increaseInvestment(1000.0);

So, what can I do to get access to the interface of derived class objects in this case? As far as I know, downcasting to concrete type each time I need to call specific functionality is not good.
Create one more abstract class derived from this to expand the interface?
Create parallel hierarchy for each specific type I need to implement (looks a bit heavy thing to do)?

like image 622
chester89 Avatar asked Apr 22 '09 06:04

chester89


People also ask

Can a pointer of derived class point to base class?

Derived class pointer cannot point to base class.

Can you assign a derived class object to a base class object?

In C++, a derived class object can be assigned to a base class object, but the other way is not possible.

What happens when a reference to a derived class object is assigned to a base class reference variable?

when we create a child class object,the base class object is auto initiated so base class reference variable can point to child class object. but not vice versa because a child class reference variable can not point to base class object because no child class object is created.

What is a pointer to derived class?

A pointer to derived class is a pointer of base class pointing to derived class, but it will hold its aspect. This pointer of base class will be able to temper functions and variables of its own class and can still point to derived class object.


2 Answers

A solution to accessing more derived class features from a base class is the visitor pattern.

class BaseBankAccount {
public:
    ...
    virtual void AcceptVisitor(IVisitor& v) = 0;
};


class AccountTypeA : public BaseBankAccount {
public:
   void TypeAFeature() {...}

   void AcceptVisitor(IVisitor& v)
   {
       v.VisitAccountTypeA(*this);
   }
};

class AccountTypeB : public BaseBankAccount {
public:
   void TypeBFeature() {...}

   void AcceptVisitor(IVisitor& v)
   {
       v.VisitAccountTypeB(*this);
   }
};

class IVisitor {
public:
    virtual void VisitAccountTypeA(AccountTypeA& account) = 0;
    virtual void VisitAccountTypeB(AccountTypeB& account) = 0;
};

class ConcreteVisitor : public IVisitor{
public:
    void VisitAccountTypeA(AccountTypeA& account) 
    {
         account.TypeAFeature(); //Can call TypeA features
    }

    void VisitAccountTypeB(AccountTypeB& account) 
    {
         account.TypeBFeature(); //Can call TypeB Features
    }
};

The interaction is not immediately obvious. You define a pure virtual method AcceptVisitor in your base class, which takes an Object of type IVisitor as a parameter. IVisitor has one Method per derived class in the hierarchy. Each derived class implements AcceptVisitor differently and calls the method corresponding to its concrete type (AccountTypeA & AccountTypeB), and passes a concrete reference to itself to the method. You implement the functionality that uses the more derived types of your hierachy in objects deriving from IVisitor. Wikipedia: Visitor Pattern

like image 188
TheFogger Avatar answered Oct 19 '22 09:10

TheFogger


Why do you need "access to the interface of derived class objects" ?

It might help for the purposes of discussion if you provide an example of a subclass of BaseBankAccount with a method you want to call.

I assume the pure methods in your BaseBankAccount class are meant to be virtual as well?

If you want to call methods of sub-classes of BaseBankAccount you would typically need to add those methods (as virtual) to the BaseBankAccount base class. If the methods doesn't make sense for all sub-classes of BaseBankAccount then you may need to rethink your class design.

E.g.

class BaseBankAccount {
    public:
        BaseBankAccount() {}

        virtual void someNewMethod () = 0;

        // ...
};

class SavingsBankAccount : public BaseBankAccount {
    public:
        virtual void someNewMethod () {
            // ...
        }

        // ...
};
like image 1
jon-hanson Avatar answered Oct 19 '22 07:10

jon-hanson