Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [Solved] returning custom Object from function
QtWS25 Last Chance

[Solved] returning custom Object from function

Scheduled Pinned Locked Moved General and Desktop
12 Posts 4 Posters 2.8k 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.
  • M Offline
    M Offline
    maximus
    wrote on last edited by
    #1

    Hi, I have a small problem understanding how to return an object from a function in C++,

    I'm loosing some of the object attribute while returning it. In the code below, the function "parseSingleWorkoutXml(QString filePath)" return a custom object "Workout", "Workout" contain a QList<Interval> which is another custom object. For some reason, when I exit the function "parseSingleWorkoutXml", the QList<Interval> size is now 0 even if before the return it had element in it.

    Both of my custom Object are declared with Q_DECLARE_METATYPE and are coded so that they can be used in QList (copy constructor, etc.) Any help appreciated! thanks

    Main function :

    @QList<Workout> XmlUtil::getLstWorkoutLocal() {

    QStringList lstWorkoutPat = Util::getListWorkoutFiles();
    
    QList<Workout> lstWorkout;
    Workout workout;
    
    foreach (QString filePath, lstWorkoutPat)
    {
        workout = parseSingleWorkoutXml(filePath);
        if (workout.getId() != -1) {
            lstWorkout.append(workout);
        }
    }
    return lstWorkout;
    

    }@

    Helper function:

    @Workout XmlUtil::parseSingleWorkoutXml(QString filePath) {

    QList<Interval> lstIntervalSource;
    //[... add element to lstIntervalSource, but after the return below, those element are no longer present?]
    workout = Workout(666, lstIntervalSource, lstRepeat,
                      name, creator, description, plan, type );
    return workout;
    

    }@


    Free Indoor Cycling Software - https://maximumtrainer.com

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

      Hi,

      Are you sure your workout object's id is not -1 ?

      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
      • JeroentjehomeJ Offline
        JeroentjehomeJ Offline
        Jeroentjehome
        wrote on last edited by
        #3

        Hi,
        To copy an QObject derived class is "impossible". Think about it, are the children of the first object also copied, if so, who is the parent of those objects, They can't have two parents, now can they?
        To do a copy by reference (return value for the getLstWorkoutLocal function) instead of by value for the QList and you should do fine.
        Second, returning a function scope variable reference is not so great, so make the QList on the heap (using the new keyword).

        Greetz, Jeroen

        1 Reply Last reply
        0
        • M Offline
          M Offline
          maximus
          wrote on last edited by
          #4

          Yes thanks SGaist i'm sure it's not -1, If I put a debug here I see the problem in action:
          @//size Source inside function 2
          //size Source after return from function 0 @

          Jeroenje thanks for your answer, sorry it's a bit hard coming from Java trying to always think of the memory under the hood, I would be happy to code and not always have to think about it! [sad_face]
          Joke aside, returning a QList<Workout> from "getLstWorkoutLocal" is not causing problem it seems, but you say it is bad practice to return a local variable, why is that exactly?

          My main problem is from the function "parseSingleWorkoutXml", I will try to return a pointer to a Workout instead of a Workout and see. But since I have a QList<Workout> and not QList<Workout*> on the top level, I will have to do some pointer arithmetic to do I guess to change Workout* back to a Workout

          If you can highlight the code you think is not so great in red I would be really glad, got dogecoin wallet? thank you!


          Free Indoor Cycling Software - https://maximumtrainer.com

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

            Just to be sure, is your Workout class deriving from QObject ?

            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
            • M Offline
              M Offline
              maximus
              wrote on last edited by
              #6

              Oh I forgot to mention, Workout and Interval are plain C++ object (not QObject)

              Exemple (stripped down a bit)

              @class Interval
              {

              public:

              enum StepType
              {
                  NONE,
                  FLAT,
                  PROGRESSIVE,
              };
              
              Interval();
              Interval(int id, QTime duration, QString displayMessage,
                       StepType powerStepType, double targetFTP_start, double targetFTP_end, int targetFTP_range, double leftPowerTarget,
                       StepType cadenceStepType, int targetCadence_start, int targetCadence_end, int cadence_range,
                       StepType hrStepType, double targetHR_start, double targetHR_end, int HR_range);
              Interval( const Interval& other );
              ~Interval();
              bool operator==(const Interval &other) const;
              friend QDataStream& operator<<(QDataStream& out, const Interval& interval);
              friend QDataStream& operator>>(QDataStream& out, Interval& interval);
              
              
              /// -------------------- setters -----------------------
              void setId(int id) {
                  this->id = id;
              }
              

              [...]
              };
              Q_DECLARE_METATYPE(Interval)@


              Free Indoor Cycling Software - https://maximumtrainer.com

              1 Reply Last reply
              0
              • A Offline
                A Offline
                andreyc
                wrote on last edited by
                #7

                Do you provide all necessary functions to make your class assignable

                "Here's an example custom data type that meets the requirement of an assignable data type:":http://qt-project.org/doc/qt-5/containers.html#the-container-classes
                @
                class Employee
                {
                public:
                Employee() {}
                Employee(const Employee &other);

                Employee &operator=(const Employee &other);
                

                private:
                QString myName;
                QDate myDateOfBirth;
                };
                @

                1 Reply Last reply
                0
                • M Offline
                  M Offline
                  maximus
                  wrote on last edited by
                  #8

                  ahhhh I found it, my copy constructor what not updated with the new field that I added!

                  Thank you very much all, i'm starting to get the hang of this language ;)

                  @/// Copy Constructor
                  Workout::Workout( const Workout& other ) {

                  this->id = other.id;
                  this->lstInterval = other.lstInterval;
                  this->lstIntervalSource = other.lstIntervalSource;  // Forgot to add!
                  this->lstRepeat = other.lstRepeat;
                  this->name = other.name;
                  this->createdBy = other.createdBy;
                  this->description = other.description;
                  this->plan = other.plan;
                  this->type = other.type;
                  this->durationMinutes = other.durationMinutes;
                  this->durationQTime = other.durationQTime;
                  this->maxPowerPourcent = other.maxPowerPourcent;
                  

                  }@


                  Free Indoor Cycling Software - https://maximumtrainer.com

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    andreyc
                    wrote on last edited by
                    #9

                    I would suggest to move this code to a function and call that function from the copy constructor and from an assignment operator. This way you don't need to duplicate your typing and you if you miss some variables then you will miss it in consistent way :-).

                    1 Reply Last reply
                    0
                    • M Offline
                      M Offline
                      maximus
                      wrote on last edited by
                      #10

                      hehe thanks for the tip, yeah it's likely i'll forget this again!
                      In fact I just have this code in the copy constructor, I didn't provide an assignement operator.

                      I just read this :
                      If we don't provide a copy constructor or an assignment operator, C++ provides a default implementation that performs a member-by-member copy.

                      So i'll try to remove my copy constructor, that way I don't have to code it and the default should do the job!
                      Thanks!


                      Free Indoor Cycling Software - https://maximumtrainer.com

                      1 Reply Last reply
                      0
                      • A Offline
                        A Offline
                        andreyc
                        wrote on last edited by
                        #11

                        Default copy constructor will work correctly only if all class variables provides their own copy constructors. Standard types like int, bool, etc provide it.
                        You need to be careful with default copy constructor and default assignment operator.

                        1 Reply Last reply
                        0
                        • M Offline
                          M Offline
                          maximus
                          wrote on last edited by
                          #12

                          Thanks for the heads up,

                          For now, I guess they all qualify as standard type, QList with custom object seems to work also, my object shouldn't change much for now so being lazy i'll use the default copy constructor ;)

                          Workout variables :
                          @ QList<Interval> lstInterval;
                          QList<Interval> lstIntervalSource;
                          QList<RepeatWidget*> lstRepeat

                          int id;
                          QString name;
                          QString createdBy;
                          QString description;
                          Type type;
                          QString plan;
                          double maxPowerPourcent;
                          double durationMinutes;
                          QTime durationQTime;@
                          

                          Interval variables :
                          @ int id;
                          QTime duration;
                          QString displayMessage;

                          StepType powerStepType;
                          double targetFTP_start;
                          double targetFTP_end;
                          int targetFTP_range;
                          double leftPowerTarget;
                          
                          StepType cadenceStepType;
                          int targetCadence_start;
                          int targetCadence_end;
                          int targetCadence_range;
                          
                          StepType hrStepType;
                          double targetHR_start;
                          double targetHR_end;
                          int targetHR_range;@
                          

                          Free Indoor Cycling Software - https://maximumtrainer.com

                          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