Solved

Request for member which is of non class type

Posted on 2014-02-23
14
1,557 Views
Last Modified: 2014-02-28
Hi

I receive the error when trying to comile, it mentions that "addSoft" is of non-class type "SoftList*".
I am trying to create a container which I want to write to and read from and am getting stuck trying to understand how to access this container.


#include "softwriter.h"
#include "softList.h"
#include <QFile>
#include <QTextStream>
#include <QDebug>

SoftWriter::SoftWriter(){
   
}

void SoftWriter::write(Soft &s){
       sl.addSoft(s);
}
QString SoftWriter::read()
{
    QFile file(fileName);
    file.open(QIODevice::ReadOnly | QFile::Text);
    QTextStream in(&file);
    QString line = in.readLine();
    do
    {
        qDebug()<< line;
        line=in.readLine();
    }while(!in.atEnd());

   file.close();

}

Open in new window


#ifndef SOFTWRITER_H
#define SOFTWRITER_H

#include "soft.h"
#include "softList.h"
class SoftWriter{
public:
    SoftWriter();
    void write(Soft& s);
    QString read();
private:
    QString fileName;
    SoftList* sl;
};
#endif // SOFTWRITER_H

Open in new window


#ifndef SOFTLIST_H
#define SOFTLIST_H

#include <QList>
#include "soft.h"

class SoftList : public QList<Soft*> {

  public:

    SoftList();

    Soft* addSoft(Soft* s);

    void deleteAll() {qDeleteAll(*this);}

};
#endif // SOFTLIST_H

Open in new window


#include "softlist.h"

SoftList::SoftList(){}

Soft* SoftList::addSoft(Soft* s) {
        append(s);
    return s;
}

Open in new window

0
Comment
Question by:devguru001
  • 6
  • 4
  • 3
  • +1
14 Comments
 
LVL 32

Expert Comment

by:phoffric
ID: 39881596
>> SoftList* sl;
>> sl.addSoft(s);
 sl is defined as a pointer; but then you use it as a class. Use -> instead of dot.
0
 
LVL 32

Expert Comment

by:phoffric
ID: 39881600
>> Soft* addSoft(Soft* s);
>> void SoftWriter::write(Soft &s){  sl->addSoft(s);
Another problem: you declare addSoft as taking in a pointer arg, but then you are passing in s, which is not a pointer; rather, it is a reference.
0
 

Author Comment

by:devguru001
ID: 39881647
Thanks, like this?

void SoftWriter::write(Soft &s){
       sl->addSoft(&s);
}

Open in new window


I tried running it like this and then it bombed out when I wanted to add to the list, I have attached the program:

Error - RtlWerpReportException failed with status code :-1073741823. Will try to launch the process directly
RtlWerpReportException failed with status code :-1073741823. Will try to launch the process directly
A1Q1.zip
0
 
LVL 32

Expert Comment

by:phoffric
ID: 39881652
>> sl->addSoft(&s);
yes, that solves two of your compilation problems.
Looks like you are running now, but have other run-time problems. Could you do me a favor. Please ask the run-time problem in another question for a faster response. Otherwise, I will try to download QtCreator next weekend and see if I understand what your problem is. During the week, I don't have much time to help due to a heavy work-load.
Thanks,
Paul
0
 

Author Comment

by:devguru001
ID: 39881660
Ok Paul, as you can see, I am struggling. I will have to close this question only once I can verify that it works. Will post the other question in the interim.
0
 
LVL 1

Accepted Solution

by:
philrosenberg earned 500 total points
ID: 39882110
I think you have a dangling pointer
sl is a pointer to a SoftList, but nowhere do you actually make it point to a SoftList. The fix depends upon exactly what you want to acheive.

The naive fix would be to use new to create a SoftList in the constructor of SoftWriter then delete it in the destructor.

If however your intention is use SoftWriter to deal with a list that already exists then you should pass a pointer to a SoftList in as a parameter to the SoftWriter constructor and assign it there.

There are possible problems there - how do you keep track of whether SoftWriter should delete the pointer or if some other part of your code should, or is is a pointer to a SoftList created on the stack (i.e. not created using new). A better way would be to use std::shared_ptr (use this for a pointer created using new that you want to share between objects - it automatically deletes the pointer at the correct time)

If however you are not dealing with a list that already exists and the list will only exist within the SoftWriter class then why use a pointer at all, make your SoftList an object rather than a pointer and then you don't have to deal with any of this mess.

I haven't put any code in here because it sounds like you are still getting to grips with how pointers work and it is best if you take these comments and work out for yourself which bits of code to change rather than copying and pasting from me.

Note that dangling pointers (pointers that point to nothing or point to things that no longer exist) along with buffer overruns (trying to access an element in an array past the end) are the source of almost every run-time bug in almost every C++ program - at least in my experience. They are also very difficult to find. So if you can avoid using raw pointers then you should. It will save you lots and lots of time in the future.
0
 

Author Comment

by:devguru001
ID: 39882210
Hi Phil

Thanks for your feedback. Yes, the part that I am really struggling with is making the list persistent. I originally was writing to text file without issue, but now I have just really confused myself as I can not figure out where to construct the QList so that it is always available. I have been spending days on this simple thing as I am struggling but will look at trying out what you have said. But right now I am trying to see why the program bombs out.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 1

Expert Comment

by:philrosenberg
ID: 39882285
So it bombs out because you do
sl->addSoft(s);

Open in new window

But when you do this you haven't told sl to point to anything, so your code goes to some random bit of memory and tries to treat what it finds there as a SoftList. This of course doesn't work. You are actually lucky that it bombs out. In the worst case your program could silently overwrite what it finds there with whatever you have told it to write and carry on regardless. Then when the actual variable that is using that memory tries to use it, it finds it has been corrupted and causes your program to crash. This is really difficult to debug because the crash happens at a point in your code which is nothing to do with the actual bug.

So you need something like
 sl=&someAlreadyExistingListThatYouKnowWontGoOutOfScope;

Open in new window

or
sl=somePointerToAnAlreadyExistingListThatYouKnowWontGoOutOfScope;

Open in new window

or
sl=new SoftList;

Open in new window

with a paired
delete sl;

Open in new window

If you don't know how scope works or how new and delete work then you need to make yourself very familiar with these before you will be able to get this to work.

Good luck

Phil
0
 
LVL 32

Expert Comment

by:sarabande
ID: 39882292
to add to above comments:

you should take the advice phil has given and avoid pointers. if you do so, the main problem you are facing probably is not 'how to use pointers' but 'how to avoid pointers'. that's why i try to give some code snippets where you have to make changes:

(1) change QList<Soft*> to QList<Soft>

if Soft is not a baseclass and the SoftList is the only container for Soft objects, you would store objects in the list and not pointers.

so class SoftList would be derived from QList<Soft> .

Note, as class SoftList has no member data and no member functions which were not provided by the baseclass as well, you also could make a typedef.

typedef QList<Soft> SoftList;

Open in new window


(2) Using a member of SoftList and not a pointer member

class SoftWriter has a list of 'Soft' objects as member.the 'write' member function actually doesn't make 'write' but adds a 'Soft' to the container. if that is intended you should name the function 'add' or similar. you might have another function 'write' or 'store' which writes the whole container to a file or database. the 'read' function also is not well-defined. it is more an 'import' but a 'read' or 'load'. moreover, the "parsing" of the lines read from file is not yet done. i suppose you would create Soft objects from the lines and add them to the list.

alltogether would lead to a class like

class SoftWriter{
public:
    SoftWriter(const QString & fn) : filename(fn) {}
    void add(const Soft& s) { sl.append(s); }
    bool load();   // reads all entries from file and adds them to list
    bool store(); // stores all entries to file
private:
    QString fileName;
    SoftList sl;   // no pointer here
}; 

Open in new window


3. Add a 'Soft' to list handled by Softwriter

if you need to 'add' a Soft to the list - for example in the 'load' function of SoftWriter you would do it like


bool SoftWriter::load()
{
    QFile file(fileName);
    ....
    while (!in.atEnd())
    {
            line = in.readLine();
            Soft soft;      
            // create a Soft by parsing text from line
            if (soft.parse(line) == true)
            {
                    add(soft);   // appends a copy of soft to list

Open in new window


hope, that helps.

Sara
0
 

Author Comment

by:devguru001
ID: 39882302
Hi Sara,

Thanks for your input, I had told Phil that I previously used a text file and am now changing to container, that is why you see some left over names and code from the file story. I do appreciate your input but am quickly trying Phil's advice first, I will respond soon.
0
 

Author Comment

by:devguru001
ID: 39882311
@Phil

I hope I am going in the right direction, I have made a change.
What do you think of this, I have added SoftList to my Soft Input class as follows:
SoftInput header:
class SoftInput: public QWidget{
    Q_OBJECT
public:
    SoftInput();
    ~SoftInput();

public slots:
    void readFromGUI();
    void writeToConsole();

private:
    void clear();
    void setupGUI();
    void saveSoft(QString sN,QDate sD,bool sR);

    QLineEdit *nameSoft;
    QDateEdit *dateSoft;
    QCheckBox *recSoft;
    QDateEdit *dateEntry;
    QPushButton *add, *display;
    SoftWriter *sw;
    SoftList *sl;
};

Open in new window


SoftInput cpp:
SoftInput::SoftInput(){
    setWindowTitle("Software Review");
    sw = new SoftWriter();
    sl = new SoftList();
    setupGUI();
}

Open in new window

0
 
LVL 1

Expert Comment

by:philrosenberg
ID: 39882364
Unfortunately you still have some way to go. Ask yourself these questions
Does Each SoftWriter have its own SoftList. If so scrap the pointers and replace SoftList *sl with SoftList sl, then all your problems are over.
If, however, the SoftList is shared between multiple SoftWriters then ask yourself these questions:
Does any other object need the SoftList?
How does the SoftWriter know which SoftList to write to?
Where will the SoftList be created and what is its scope and lifetime?
If you create a SoftList with new then where will the matching delete call be made.

If you can't answer these questions then I think you need to go back to basics regarding C++. I would recommend "C++ In Action: Industrial-Strength Programming" by Bartosz Milewski. It is quite old, but it teaches good style even more than the syntax which I think would be very helpful for you in this case and probably starts at the right level for what you are doing. It is available for free online at http://www.relisoft.com/book/
0
 

Author Comment

by:devguru001
ID: 39882380
I am sure I am right, take a look:
SoftInput::SoftInput(){
    setWindowTitle("Software Review");
    sw = new SoftWriter();
    sl = new SoftList();
    setupGUI();
}

 SoftInput::~ SoftInput(){
    delete sw;
    delete sl;
}

void  SoftInput::setupGUI(){
    QLabel* titName = new QLabel("Software Name");
    nameSoft = new QLineEdit();
    QLabel* titDate = new QLabel("Review Date");
    dateSoft = new QDateEdit();
    QLabel* titRec = new QLabel("Recommened Software");
    recSoft = new QCheckBox();
    add = new QPushButton("Add Review");
    display = new QPushButton("Display Reviews");
    QGridLayout* layout = new QGridLayout(this);

    layout->addWidget(titName, 0, 0);
    layout->addWidget(nameSoft, 0, 1);
    layout->addWidget(titDate, 1, 0);
    layout->addWidget(dateSoft, 1, 1);
    layout->addWidget(titRec, 2, 0);
    layout->addWidget(recSoft, 2, 1);
    layout->addWidget(add, 3, 0);
    layout->addWidget(display, 3, 1);
    this->setLayout(layout);

    connect(add, SIGNAL(clicked()), this, SLOT(readFromGUI()));
    connect(display, SIGNAL(clicked()), this, SLOT(writeToConsole()));
}

void SoftInput::readFromGUI() {
    QString nS = nameSoft->text();
    QDate dS = dateSoft->date();
    bool rS = recSoft->isChecked();

    if(!nS.isEmpty() && !dS.isNull()){
        saveSoft(nS, dS, rS);
        clear();
    }
    else {
        QMessageBox::information(this, "Film Information", "Enter all the necessary information");
    }
}

void SoftInput::writeToConsole() {
    sw->read(sl);
}

void SoftInput::saveSoft(QString nS, QDate dS, bool rS){
    Soft s(nS,dS,rS);
    sw->write(s,sl);
    QMessageBox::information(this, "Software Review", "Software Review has been saved");
}

void SoftInput::clear(){
    nameSoft->clear();
}

Open in new window

0
 
LVL 1

Expert Comment

by:philrosenberg
ID: 39883753
Hi
You haven't posted your SoftWriter class so I can't tell if what you have done works. Of course you have the code and you can test it, so the easy way to check if you are right is to try and see if it does what you intend.

However, to me it looks like it can't be right. You do not pass your sl pointer to sw at any point, so sw cannot know about sl. Not unless you have done something that you haven't shown.

I really really would recommend you have a look at the book I suggested. Even just the Introduction and the language chapters would give you skills you need. Plus the online version is free. I have a hard copy and it's one of the best books I ever bought. I think you just haven't got the knack of C++ scope yet and that book will explain it better than I can.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now