0

this is my first question on this website, but I will try to cover everything that is needed. Apologies if I forgot something. I encountered the problem using QT Creator, but I suppose it would be the same using Visual Studio, or just C++ in general.

I've got a couple of classes: Mainwindow, Track and AddForm. Mainwindow is what it is called. The main form. Track is a custom class based on QObject which contains just a single QString variable (just for now, since I am still experimenting with QT). And AddForm is a class for another form that can be created by clicking a button in my MainWindow form. That form only contains a single line-edit to fill the string and a button that says "Add". Whenever that button is pressed the text from the line-edit will be put into the QString variable from the Track-class. That QString variable is called "artist".

Apart from assigning the text from the line-edit to the variable "artist" for the Track-object, the form will also emit a signal that sends that entire object. A slot within my mainwindow will react to that signal and collect the Track-object. So far so good.

Here is my question. Within my mainwindow-header I have created a private QVector named trackVector, which I can then call within my mainwindow.cpp. What I want to do is append / push_back the QVector with that Track-object. Sort of like this:

trackVector.push_back(trackObject);

I get the following error message when building the application: click here for a screenshot

Now ofcourse with an integer or any other variable this is very straightforward. You would just do something like this I suppose:

QVector<int> myVector;
myVector.push_back(3);

I think that whenever you append a QVector (or a standard non-QT vector) you need to do so with the constructor of that class. But how can I make a constructor in which you can just put an already existing object?

Please explain with as much simple words as possible since I am no native English speaker :) Thanks a lot in advance!

MartijnKor
  • 82
  • 1
  • 9
  • The error says that you try to push a *pointer* to a `Track` object, when the vector is a vector of `Track` *objects* (not pointers). – Some programmer dude May 31 '16 at 17:16
  • thanks! So you think it will work whenever it isn't a pointer. Do you know how to make it a non-pointer so to speak? – MartijnKor May 31 '16 at 17:18
  • Either don't pass a pointer to the `trackAdded` function, or dereference the pointer. – Some programmer dude May 31 '16 at 17:19
  • Then I get the following error message: use of deleted function Track::Track(const Track&) – MartijnKor May 31 '16 at 17:24
  • 1
    @MartijnKor -- If you decide to make it `vector`, make sure that `Track` is safely copyable, i.e. no side-effects if you copy those objects. The `vector` will be making copies, and if `Track` does not have correct copy semantics, you will run into runtime issues. – PaulMcKenzie May 31 '16 at 17:24
  • @PaulMcKenzie at the moment I didn't find any issues with it sending it with signals and slots but thanks I will keep it in mind. – MartijnKor May 31 '16 at 17:25
  • 1
    @MartijnKor - If that's the error, then this goes back to my comment. The `vector` will make copies, and if your class has removed the ability to make copies (by making the copy constructor "deleted"), it cannot be placed in a vector. One thing you can do is to have a vector of pointers (better smart pointers) as you had done in the beginning, and provide the proper code to place such a pointer in the vector. – PaulMcKenzie May 31 '16 at 17:28
  • @PaulMcKenzie could you maybe explain with an example, since I unfortunately don't really understand what you mean by that :( – MartijnKor May 31 '16 at 17:30
  • @MartijnKor -- The `std::vector` is a class that internally will be making copies of the object(s) you place in it. Since the author of the `Track` object turned off the ability to copy, you can't place `Track` in a vector. It's that simple. So instead of `vector`, you can have a vector of pointers to `Track`, i.e. `vector`. But again, this makes the code more brittle as you have to maintain those pointers. That's why a vector of smart pointers would be better. – PaulMcKenzie May 31 '16 at 17:32
  • I believe that the smart pointers @PaulMcKenzie is referring to are shared pointers. Here's [one example](http://stackoverflow.com/a/1552513/5209610) and [another example](http://stackoverflow.com/a/24049214/5209610) of the use of shared pointers in C++. – Vladislav Martin May 31 '16 at 17:33

1 Answers1

1

You've posted insufficient code (so your post is liable to be closed as off topic -- a classical beginners error on SO), but I guess the appropriate solution here is to use some auto pointer type. If your TrackVector is to keep ownership of the Track objects, then the best solution is have std::unique_ptr<Track> elements:

std::vector<std::unique_ptr<Track>> TrackVector;
// filled like
TrackVector.emplace_back(new Track(args));

If, on the other hand ownership lies somewhere else, you may either use std::shared_ptr or even raw pointers (provided your layout guarantees that the pointed to Track objects' lifetime exceeds that of the TrackVector).

Walter
  • 44,150
  • 20
  • 113
  • 196