[SOLVED]Pointer class problem
-
Hi all
I am busy with a QT exercise where I have to write a console app, impliment an asset class and three types of asset classes(bond, saving and stock) that inherits from Asset. I also have to impliment a class called assetList which derives from QList and only contains pointers to assets as elements. I'm not sure at all how to go about the assetList class. In the addAsset function how could I loop through the list using a foreach loop without having a name for the list? Could I use this? i'm also not sure if my constructor is ok. In the UML diagram the constructor doesn't have any parameters which confuses me a bit...
my code:
@
Asset.h#ifndef ASSET_H
#define ASSET_H
#include <QString>
#include <QDate>class Asset {
public:
Asset(QString des, QDate dat);
virtual double value() = 0;
QString getDescription() const;
QString getType() const;
protected:
QString type;
QDate date;
private:
QString description;
};#endif // ASSET_H
asset.cpp
#include <QString>
#include "Asset.h"Asset::Asset(QString des, QDate dat) {}
//double Asset::value(){
//return value;
//}QString Asset::getDescription() const {
return QString("%1").arg(description);
}QString Asset::getType() const {
return QString("%1").arg(type);
}assetList.h
#ifndef ASSETLIST_H
#define ASSETLIST_H#include <QList>
#include "Asset.h"
class AssetList : public QList<Asset*>
{
Q_OBJECT
public:
explicit AssetList();
~AssetList();
bool addAsset(Asset* a);
Asset* findAsset(QString des);
double totalValue(QString typ);signals:
public slots:
};
#endif // ASSETLIST_H
assetList.cpp
#include "AssetList.h"
#include "Asset.h"AssetList::AssetList() {
QList<Asset*> list;
}AssetList::~AssetList(){
qDeleteAll(*this);
clear();
}bool AssetList::addAsset(Asset *a){
bool duplicateAsset = false;foreach(asset* b, this) { if (b->getDescription() == a->getDescription()) duplicateAsset = true; } if (duplicateAsset == true) { cout << "Unable to add duplicate asset to list "; break; } else: list.append(a); }
Asset* AssetList::findAsset(QString des) {
asset* searchItem;foreach(asset* b, list) { if (b->getDescription() == des) searchItem = b; else searchItem = 0; } return searchItem;
}
double AssetList::totalValue(QString typ){
double totalValue = 0;foreach(asset* b, list) { if (b->getType() == typ) totalValue += b->value(); } return totalValue;
}
bond.h
#ifndef BOND_H
#define BOND_H
#include "Asset.h"class Bond : public Asset
{
public:
Bond(QString des, QDate dat, double fva, double yie);
double value();
private:
double faceValue;
double yield;
};#endif // BOND_H
bond.cpp
#include "Bond.h"
Bond::Bond(QString des, QDate dat, double fva, double yie)
: Asset(des, dat), faceValue(fva), yield(yie)
{
}double Bond::value() {
QDate tempDate;
tempDate.currentDate();
double interestEarned = tempDate.year() - date.year();
double totalEarned = interestEarned * faceValue;
return totalEarned;
}Stock.h
#ifndef STOCK_H
#define STOCK_H
#include <QString>
#include "Asset.h"class Stock: public Asset {
public:
Stock(QString des, QDate dat, int nsh, double spr);
double value();
double setPrice(double np);
private:
int numShares;
double sharePrice;};
#endif // STOCK_H
Stock.cpp
#ifndef STOCK_H
#define STOCK_H
#include <QString>
#include "Asset.h"class Stock: public Asset {
public:
Stock(QString des, QDate dat, int nsh, double spr);
double value();
double setPrice(double np);
private:
int numShares;
double sharePrice;};
#endif // STOCK_H
saving.h
#ifndef SAVING_H
#define SAVING_H
#include "Asset.h"class Saving : public Asset
{
public:
Saving(QString des, QDate dat, double cva, double ira); //Saving constructor
double value();
double changeValue(double amount);
void addInterest();
private:
double currentValue;
double interestRate;
};#endif // SAVING_H
saving.cpp
#include <QString>
#include <QDate>
#include "saving.h"Saving::Saving(QString des, QDate dat, double cva, double ira)
: Asset(des, date), currentValue(cva), interestRate(ira) {
}double Saving::value() {
return currentValue;
}double Saving::changeValue(double amount) {
if (amount >= 0)
currentValue += amount;
else
currentValue -= amount;
return currentValue;
}void Saving::addInterest() {
currentValue += ((currentValue / 100) * (interestRate / 12));
}main.cpp
#include <QString>
#include <QTextStream>
#include <QDate>
#include "Stock.h"
#include "Bond.h"
#include "AssetList.h"QTextStream cin(stdin);
QTextStream cout(stdout);int main() {
QString type, dat, des;
QDate date;
int numShares;
double sharePrice, faceValue, yield;cout << "Enter Asset type: "; cin >> type; cout << "Enter description: "; cin >> des; cout << "Enter date YY/MM/DD"; cin >> dat; date.fromString(dat); if (type == "Stock" || type == "stock" || type == "STOCK") { cout << "Enter number of shares "; cin >> numShares; cout << "Enter the sharePrice "; cin >> sharePrice; Stock(des, date, numShares, sharePrice); } else if (type == "Bond" || type == "bond" || type == "BOND") { cout << "Enter face balue: "; cin >> faceValue; cout << "Enter yield: "; cin >> yield; Bond(des, date, faceValue, yield); } return 0;
}
@ -
Hi,
You AssetList class is not correct. You are deriving from QList which destructor is not virtual so your destructor won't be called. Also you have a QList member in your QList derived class which doesn't make sense.
So now the design question is: do you need a class that encapsulate a list or a list class ?
-
Personally, I prefer for-range loops over for_each. So my implementation would look something like the following:
@
bool AssetList::addAsset(const Asset* asset)
{
auto duplicateAsset = false;for(const auto& assetChild : *this) { if(assetChild->getDescription() == asset->getDescription()) { duplicateAsset = true; break; } } if(duplicateAsset == true) { cout << "error message" << endl; } else { this->push_back(asset); }
}
@Something like the above would be what I'd attempt.
If you must use std::for_each():@
std::for_each(std::begin(*this), std::end(this),
[asset, duplicateAsset](const Asset childAsset)
{
if(childAsset->getDescription() == asset->getDescription()
{
duplicateAsset = true;
}
});// do work
@
As you can see, std::for_each gets a little more complicated and the above example would be using lambda functions.
I think the for-range loop is much easier to read and understand.
Hope this helps
-
First off, SGaist is correct, Im still new to Qt, isn't realize you couldn't inherit QList. You need to get rid of the inheritance and keep the list member variable.
childAsset refers to a child object in the list. The for loop iterates through each item in the list and is called childAsset. Read up on range based for loops.
-
I didn't say that you can't do that. You can inherit QList (take for example QQueue) It's just that there are some limitation on what you can do.
Since AssetList is a QList, why does it contain a QList member variable ?
-
That is a c++11 range-based for loop, (just google it), and the meaning of "auto" has also changed with c++11 so it depends on your compiler or the compiler flags if you can use that or not. With a qmake based project you can just use this in your project file:
@
CONFIG += c++11
@
In your case using "auto" type inference doesn't make much sense, so you can just use the correct types since there aren't that complicated I guess (who uses "auto b = false" anyways haha).so instead of
@
for(const auto& assetChild : *this)
@
you can just write
@
for(const Asset *assetChild : *this)
@
or Qt foreach style (works without any c++11 compiler features)
@
foreach(const Asset *assetChild, *this)
@if you want use a default for loop, but I think it's more readable like this.