problems with polymorphism

Started by
3 comments, last by Antheus 16 years, 3 months ago
The foolwoing codes produces, errors by where i have the classes Payment credit : payment cheque : payment cash : payment yet when i cast the payment pointer to one of the child classes, that pointer is not able to access the child classes methods. main

			Payment * p = iter->theirOrders.getPaymentPointer(); //retuns an address to the pointer 

			if( p != NULL)
			{
			
				if ( p->getPaymentType() == "Cash")
				{
					//nothing to write
				}

				if ( p->getPaymentType() == "Credit Card")
				{
				customerListFile << "Card Number: " << p->getAccountNumber();
				customerListFile << "Expiry Date: " << p->getExpDate();
				customerListFile << "Card Type: " << p->getType();
				}

				if ( p->getPaymentType() == "Cheque")
				{
				customerListFile << "Bank Name: " << p->getBankName();
				customerListFile << "Account Number: " << p->getAccountNumber();
				}
			}

and here are the .cpp and headers of the payment, etc

#pragma once
#include "payment.h"

class Cash :
	public Payment
{
private:
	float cashTendered;
public:
	Cash(void);
	~Cash(void);

	void payedInCash(bool cashIn);

	virtual void displayPaymentInfo();
	virtual void getpaymentInfo();
};





/////////////////////////////////////////////////////////////////

#include "Cash.h"
#include <iostream>

Cash::Cash(void) 
{
}

Cash::~Cash(void)
{
}

void Cash::payedInCash(bool cashIn)
{
	cashTendered = cashIn;
}


void Cash::getpaymentInfo()
{
	

}

void Cash::displayPaymentInfo()
{
	this->displayAmount();
}



#pragma once
#include "payment.h"
#include <string>

class Cheque :
	public Payment
{
private:
	std::string bankName;
	std::string accountNumber;
public:
	Cheque(void);
	~Cheque(void);

	std::string		getBankName();
	void			setBankName(std::string name);

	std::string		getAccountNumber();
	void			setAccountNumber(std::string Number);

	virtual void displayPaymentInfo();
	virtual void getpaymentInfo();
};



/////////////////////////////////////////////////////////////////////////


#include "Cheque.h"
#include <iostream>

Cheque::Cheque(void)
{
	bankName = "";
	accountNumber = "";
}

Cheque::~Cheque(void)
{
}

std::string	Cheque::getBankName()
{
	return this->bankName;
}

void Cheque::setBankName(std::string name)
{
	this->bankName = name;
}

std::string	Cheque::getAccountNumber()
{
	return this->accountNumber;
}

void Cheque::setAccountNumber(std::string number)
{
	this->accountNumber = number;
}

void Cheque::displayPaymentInfo()
{
	this->displayAmount();
	std::cout << "Account Number: " << this->getAccountNumber();
	std::cout << "Bank Name: " << this->getBankName() << std::endl;

}

void Cheque::getpaymentInfo()
{
	std::string bankName = "";
	std::string accountNumber = "";


	std::cout << "Enter bank Name: ";
	std::cin >> bankName;

	std::cout << std::endl;

	std::cout << "Enter account Number: ";
	std::cin >> accountNumber;

	this->setAccountNumber(accountNumber);
	this->setBankName(bankName);

}

#pragma once
#include "payment.h"
#include <string>

class Credit :
	public Payment
{
// add your pre and post statements here
private:
	std::string number;
	std::string type;
	std::string expDate;
public:
	Credit(void);
	~Credit(void);

	std::string getNumber();
	void setNumber(std::string number);

	std::string getType();
	void setType(std::string type);

	std::string getExpDate();
	void setExpDate(std::string date);

	virtual void displayPaymentInfo();
	virtual void getpaymentInfo();
};



//////////////////////////////////////////////////////////////////////



#include "Credit.h"
#include <iostream>

Credit::Credit(void)
{
}

Credit::~Credit(void)
{
}

std::string Credit::getNumber()
{
	return this->number;
}

void Credit::setNumber(std::string _number)
{
	this->number = _number;
}

std::string Credit::getType()
{
	return this->type;
}

void Credit::setType(std::string _type)
{
	this->type = _type;
}

std::string Credit::getExpDate()
{
	return this->expDate;
}

void Credit::setExpDate(std::string date)
{
	this->expDate = date;
}

void Credit::displayPaymentInfo()
{
	this->displayAmount();
	std::cout << "Expiry Date: " << this->getExpDate();
	std::cout << "Number: " <<this->getNumber();
	std::cout << "Card Type: " << this->getType() << std::endl;

}

void Credit::getpaymentInfo()
{
	std::string exp = "";
	std::string num = "";
	std::string type = "";

	std::cout << "Enter expiry date: ";
	std::cin >> exp;

	std::cout << std::endl;

	std::cout << "Enter number: ";
	std::cin >> num;

	std::cout << std::endl;

	std::cout << "Enter card type (visa, American Express etc): ";
	std::cin >> type;

	std::cout << std::endl;

	this->setExpDate(exp);
	this->setNumber(num);
	this->setType(type);
}


#pragma once
#include <string>

class Payment 
{
private:
	float amount;
	std::string paymentType;
public:
	Payment();
	void displayAmount();
	void setAmount(float amount);

	void setPaymentType(std::string type);
	std::string getPaymentType();

	virtual void displayPaymentInfo() = 0;
	virtual void getpaymentInfo() = 0;
	
};




/////////////////////////////////////////////////////////////////////////

#include "Payment.h"
#include <iostream>

Payment::Payment()
{
	this->amount = 0.0f;
	this->paymentType = "Not payed yet";
}

void Payment::displayAmount()
{
	std::cout << "Amount Paid : " << this->amount;
}

void Payment::setAmount(float _amount)
{
	this->amount = _amount;
}


void Payment::setPaymentType(std::string type)
{
	this->paymentType = type;
}
std::string Payment::getPaymentType()
{

	return this->paymentType;
}


i seem to get mulitple errors like error C2039: 'getBankName' : is not a member of 'Payment' but p should now be of the type of the returned address
Advertisement
To do what you want, you'll need to cast the base type pointers to the derived type pointers. The safest way would be with dynamic_cast. Ex:
if (Credit * credit = dynamic_cast<Credit *>(p)) {  customerListFile << "Card Number: " << credit->getAccountNumber();  customerListFile << "Expiry Date: " << credit->getExpDate();  customerListFile << "Card Type: " << credit->getType();}

However, what you're trying to do isn't very good design. A better way would be to give the base class a function to dump details to a stream, and then in each derived class, have the relevant details written.
Quote:
i seem to get mulitple errors like

error C2039: 'getBankName' : is not a member of 'Payment'


That is absolutely correct. Look at the Payment class. It doesn't have any getBankName.

Quote:
yet when i cast the payment pointer to one of the child classes, that pointer is not able to access the child classes methods.


I don't see any casting in your code. In order to access the true members of the derived class, you need to cast the base class object to the derived class type(thats why you get that error). Then do something like this:

Payment * p = iter->theirOrders.getPaymentPointer(); //retuns an address to the pointer 			if( p != NULL)			{							if ( p->getPaymentType() == "Cash")				{					//nothing to write                                        Cash* c = static_cast<Cash*>(p);				}				else if ( p->getPaymentType() == "Credit Card")				{                                    Credit* c = static_cast<Credit*>(p);				    customerListFile << "Card Number: " << c->getAccountNumber();//I didnt find this method in your class				    customerListFile << "Expiry Date: " << c->getExpDate();				    customerListFile << "Card Type: " << c->getType();				}				else if ( p->getPaymentType() == "Cheque")				{                                    Cheque* c = static_cast<Cheque*>(p);				    customerListFile << "Bank Name: " << c->getBankName();				    customerListFile << "Account Number: " << c->getAccountNumber();				}			}


There are several things in your code that could be changed. The methods like getPaymentType should be virtual, and in each class you return a specific string(your code will never work because it'll always return the Payment::paymentType)(you can use typeid operator here instead).

Every method which will return specific things for each class must be declared as virtual and then overridden at the derived class. Take a better look at your code.
.
Quote:Original post by SiCrane
However, what you're trying to do isn't very good design. A better way would be to give the base class a function to dump details to a stream, and then in each derived class, have the relevant details written.

Quoted for emphasis. Type-switching is brittle, error-prone, unsafe and generally evil (See Item 90: Avoid type switching; prefer polymorphism, C++ Coding Standards by Herb Sutter and Andrei Alexandrescu).

Σnigma
Ok, so you have "virtual void displayPaymentInfo()" virtual method.

And yet, you choose to handle it externally, causing all the mess.

Polymorphism here is the following:
iter->theirOrders.getPaymentPointer()->displayPaymentInfo();


And the appropriate method will be invoked.

This topic is closed to new replies.

Advertisement