Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. [SOLVED]Pointer class problem
QtWS25 Last Chance

[SOLVED]Pointer class problem

Scheduled Pinned Locked Moved C++ Gurus
10 Posts 4 Posters 3.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    Dn588
    wrote on last edited by
    #1

    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;
    

    }
    @

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      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 ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • A Offline
        A Offline
        ASxa86
        wrote on last edited by
        #3

        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

        1 Reply Last reply
        0
        • D Offline
          D Offline
          Dn588
          wrote on last edited by
          #4

          Hi

          Which member doesn't make sense? Also if I implement it with the for loop what does assetChild refer to? So in the totalValue function I could also use "*this" to loop through the same list?

          1 Reply Last reply
          0
          • A Offline
            A Offline
            ASxa86
            wrote on last edited by
            #5

            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.

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              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 ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • D Offline
                D Offline
                Dn588
                wrote on last edited by
                #7

                In the for loop is assetChild of type assetList? I tried using auto but keep getting the error message auto will change the meaning of *this please remove it

                1 Reply Last reply
                0
                • D Offline
                  D Offline
                  Dn588
                  wrote on last edited by
                  #8

                  or could I do something like this?

                  for (int i = 0; i <= this->size() ++i)

                  1 Reply Last reply
                  0
                  • X Offline
                    X Offline
                    Xander84
                    wrote on last edited by
                    #9

                    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.

                    1 Reply Last reply
                    0
                    • D Offline
                      D Offline
                      Dn588
                      wrote on last edited by
                      #10

                      Thanks Xander. I managed to get it working with a for loop using this->at() to check the current value...

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved