Results 1 to 14 of 14

Thread: Writing a QVector subclass

  1. #1
    Join Date
    Nov 2010
    Posts
    63
    Thanks
    26
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Writing a QVector subclass

    Hi.

    I'm trying to write a subclass of QVector, since I want general (Q)Vector functionality, but add a few context specific functionalities.
    I tried to write it from scratch, but ran into some problems.

    So I had Qt Creator construct a default subclass to QVector instead (see screenshot). I tried it with and without "Inherits QObject" selected ('ssvector.h' and 'ssvector2.h' in the attached files, respectively).

    I was surprised that the default code doesn't include any "template" keywords. When I googled for inheritance from template classes the results always said the subclasses should have the "template" statement, too.
    But then from the look at the QVector source code, it isn't a template class itself, but has a template member, so I suppose that's okay.

    But the default generated code doesn't compile and I get this error in both cases (i.e. with or without QObject inheritance):

    error: expected class-name before '{' token

    in the line with the { bracket after the "class" statement.
    (shorter version code with no QObject inheritance below)

    Qt Code:
    1. #ifndef SSVECTOR2_H
    2. #define SSVECTOR2_H
    3.  
    4. #include <QVector>
    5.  
    6. class SSVector2 : public QVector
    7. {
    8. public:
    9. SSVector2();
    10. };
    11.  
    12. #endif // SSVECTOR2_H
    To copy to clipboard, switch view to plain text mode 


    So my questions are:
    What is this error ? Why do I get it with the default generated code ?
    and
    How do I go about defining a QVector subclass in general ?

    Thank you for any hint.
    Attached Images Attached Images
    Attached Files Attached Files

  2. #2
    Join Date
    May 2010
    Location
    Romania
    Posts
    1,021
    Thanks
    62
    Thanked 260 Times in 246 Posts
    Qt products
    Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Writing a QVector subclass

    The problem most likely is with the QVector that doesn't have a parent (so no constructor takes a QObject pointer as a parent) so don't pass a parent to the QVector's constructor.

  3. The following user says thank you to Zlatomir for this useful post:

    Computer Hater (19th June 2011)

  4. #3
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Writing a QVector subclass

    QVector is a template class, so your class must be a template too, or inherit from instantiated QVector<Type> class.

    edit:
    so it should look like:
    Qt Code:
    1. class MyVector : public QVector<int>{
    2. ...
    3. };
    To copy to clipboard, switch view to plain text mode 
    or:
    Qt Code:
    1. template <typename T> class MyVector : public QVector<T>{
    2. ...
    3. };
    To copy to clipboard, switch view to plain text mode 
    edit2:
    But then from the look at the QVector source code, it isn't a template class itself
    Then I guess we have different QVector sources:
    Qt Code:
    1. // from qvector.h
    2. ...
    3. template <typename T>
    4. class QVector
    5. {
    6. typedef QVectorTypedData<T> Data;
    7. union { QVectorData *p; QVectorTypedData<T> *d; };
    8.  
    9. public:
    10. inline QVector() : p(&QVectorData::shared_null) { d->ref.ref(); }
    11. explicit QVector(int size);
    12. ...
    To copy to clipboard, switch view to plain text mode 
    Yes, it is a template
    Last edited by stampede; 19th June 2011 at 17:41. Reason: typo + additional comment x2

  5. The following user says thank you to stampede for this useful post:

    Computer Hater (19th June 2011)

  6. #4
    Join Date
    Nov 2010
    Posts
    63
    Thanks
    26
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Writing a QVector subclass

    Thanks to both of you for your quick responses. Unfortunately, I didn't see them earlier.

    @Zlatomir
    You're right. QVector doesn't have a parent. I kind of assumed that since Creator showed me that that option it would have one, so I tried both versions, with and without QObject inheritance.
    Still, the version without the inheritance had the same problem.

    @stampede
    Yes, of course you're right, too. QVector is a template class. :-D
    I haven't had any practice with template classes and amidst all the trouble-shooting got it mixed up in my head. So when I noticed that Creator didn't default code the subclass as a template and I looked into the QVector source code, I was suddenly feeling unsure and got it all wrong. Sorry for the confusion. :-/

    The thing is, I did it just the way you wrote when I coded it the first time around (after some googling on template inheritance). It compiled fine, but then I ran into a problem with trying to define a copy constructor that I couldn't figure out. So I thought I'd try and see what Qt Creator default codes for me, assuming that would be a good starting point since I figured this would have to be correct. Hence the above problem and question.

    Now I went back to the original attempt, reduced to the following sample code that shows the problem with trying to use a copy constructor.


    ssvector.h

    Qt Code:
    1. #ifndef SSVECTOR_H
    2. #define SSVECTOR_H
    3.  
    4. #include <QVector>
    5.  
    6. template <class T>
    7. class SSVector : public QVector<T>
    8. {
    9. public:
    10. SSVector<T>() {}
    11. SSVector<T>(const SSVector<T>& that) {}
    12. };
    13.  
    14. #endif // SSVECTOR_H
    To copy to clipboard, switch view to plain text mode 


    main.cpp

    Qt Code:
    1. #include <QDebug>
    2. #include "ssvector.h"
    3.  
    4. int main(int argc, char *argv[])
    5. {
    6. SSVector<QString> dummy();
    7. SSVector<QString> dummy2(dummy);
    8.  
    9. return 0;
    10. }
    To copy to clipboard, switch view to plain text mode 

    The class itself compiles fine, but when I try to declare any instances in the main program, I get the following error:

    [..]/Test/main.cpp:15: error: no matching function for call to 'SSVector<QString>::SSVector(SSVector<QString> (&)())'

    [..]/Test/ssvector.h:11: candidates are: SSVector<T>::SSVector(const SSVector<T>&) [with T = QString]

    [..]/Test/ssvector.h:10: SSVector<T>::SSVector() [with T = QString]


    The line numbers are off because I removed any outcommented text. The error refers to the declaration of "dummy2" though, using the copy constructor.
    I maybe also should mention that in the original version I used both a .h and a .cpp file, but reduced it now to a (trivial) in-class definition for brevity. I get the same error in both cases.

    I don't understand the first line of the error, in particular what the bracketed ampersand "(&)" and the additional brackets "()" in the end mean, and why it doesn't recognize the given copy constructor as a matching signature.

    Again, sorry for the confusion and for only now getting to the actual problem.

  7. #5
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Writing a QVector subclass

    Qt Code:
    1. SSVector<QString> dummy();
    To copy to clipboard, switch view to plain text mode 
    Because this is declaration of a function called "dummy" taking no parameters and returning SSVector<QString>.
    Remove the brackets after "dummy" and it should work:
    Qt Code:
    1. SSVector<QString> dummy/* no () here*/;
    2. SSVector<QString> dummy2(dummy);
    To copy to clipboard, switch view to plain text mode 

  8. The following user says thank you to stampede for this useful post:

    Computer Hater (19th June 2011)

  9. #6
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Writing a QVector subclass

    Last time I played with vector, it didn't have a virtual dtor, and inheritance from a class without a virtual dtor is pure evil (IMO).

    Exactly why do you want to subclass? Would it not be better to add functions as per the STL Algorithms? This is typically what I prefer.

  10. The following user says thank you to squidge for this useful post:

    Computer Hater (20th June 2011)

  11. #7
    Join Date
    Nov 2010
    Posts
    63
    Thanks
    26
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Writing a QVector subclass

    Thank you, stampede !
    This solves the problem for the inline definitions of the constructors I used for simplification.
    However, if I put the code again in the .cpp file:

    ssvector.cpp

    Qt Code:
    1. #include "ssvector.h"
    2.  
    3. template <class T> SSVector<T>::SSVector()
    4. {
    5. }
    6.  
    7. template <class T> SSVector<T>::SSVector(const SSVector<T>& that)
    8. {
    9. }
    To copy to clipboard, switch view to plain text mode 

    I now get this error output:

    [..]/Test/main.cpp:14: error: undefined reference to `SSVector<QString>::SSVector()'
    [..]/Test/main.cpp:15: error: undefined reference to `SSVector<QString>::SSVector(SSVector<QString> const&)'
    :-1: error: collect2: ld returned 1 exit status

    Which actually was the original error that started me down this awry line of solution attempts that got me into more problems. I suppose I should have just posted the original problem when my attempts to solve it didn't work out, instead of posting subsequent problems with more mistakes in them.
    Well, lesson learned. (I hope.)

    So, is the template use in the code definition wrong ?
    It works out fine if I use non-template inheritance to, say, QChar.


    Added after 4 minutes:


    Quote Originally Posted by squidge View Post
    Last time I played with vector, it didn't have a virtual dtor, and inheritance from a class without a virtual dtor is pure evil (IMO).

    Exactly why do you want to subclass? Would it not be better to add functions as per the STL Algorithms? This is typically what I prefer.
    I'm not yet experienced enough to understand why that matters. Didn't have it come up before. I will give it some thought.
    To answer your question: I just basically wanted a QVector, with some additional functionality thrown in, so I thought inheritance was the way to go.
    Last edited by Computer Hater; 19th June 2011 at 21:05.

  12. #8
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Writing a QVector subclass

    You can't separate this code, because full template definition should be "visible" to the compiler when instantiating the template.
    Say, you want to instantiate for integers (lets simplify things):
    Qt Code:
    1. #include "ssvector.h"
    2. //now everything included in ssvector.h is visible here, that is declarations of constructors
    3.  
    4. SSVector<int> x;
    5. // compiler now generates the code:
    6. class SSVector_int : public QVector<int> /*some kind of a name is given for this specific class, lets say SSVector_int*/
    7. {
    8. public:
    9. SSVector_int() ;
    10. SSVector_int(const SSVector_int& that) ;
    11. };
    12.  
    13. // I think its now clear that constructor of SSVector_int cannot be called, because compiler dont know its definition here
    To copy to clipboard, switch view to plain text mode 
    If you want you can keep the implementation in separate file, but when you want to use the vector template class, you will have to include both files (so that "implementation" will be visible to the complier when instantiating)
    So its up to you how to fix it, I'd simply keep the implementation inline.
    Btw. answering squidge's questions could be good too

  13. #9
    Join Date
    Nov 2010
    Posts
    63
    Thanks
    26
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Writing a QVector subclass

    Thanks, stampede. That is good to know.
    But I still don't understand why there is a difference to a non-template class. You say the compiler automatically generates the given code. So the declarations are available at compile time, right ?
    Then you say the constructor cannot be called because the compiler doesn't know its definition. But isn't that the same for any non-template class that I define in a separate .cpp file ?
    What am I missing ?

    I will read up on the visibility of templates and virtual destructors, as squidge mentioned, then.

  14. #10
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Writing a QVector subclass

    But isn't that the same for any non-template class that I define in a separate .cpp file
    No, as long as you compile and link methods from the "separate .cpp file", compiler can "look" into compiled code and take any method it needs. In the template case, there is no code in separate .cpp generated for the specific template instantiation.
    So the declarations are available at compile time, right ?
    Declarations - yes, definitions - no.
    But I still don't understand why there is a difference to a non-template class.
    Because when you create non-template class derived from QVector<Type>, compiler has everything it needs - QVector<Type> is instantiated, so its like a normal class from now on.
    Main difference is in the .cpp files -
    Case 1: template-based approach:
    Qt Code:
    1. // .cpp file with template methods:
    2. template <class T> SSVector<T>::SSVector()
    3. {}
    4. template <class T> SSVector<T>::SSVector(const SSVector<T>& that)
    5. {}
    6. // compiler has a template, but when you compile this file, it does not "see" that
    7. // somewhere in other files you want to use above methods for a specific T
    To copy to clipboard, switch view to plain text mode 
    Case 2: non-template approach:
    Qt Code:
    1. // .cpp file with non-template methods
    2. #include "ssvector.h"
    3. // include actually pastes the file content, so it looks like:
    4. class SSVector : public QVector<int/*or anything else*/>
    5. {
    6. public:
    7. SSVector();
    8. SSVector(const SSVector& that);
    9. };
    10.  
    11. SSVector::SSVector()
    12. {}
    13. SSVector(const SSVector& that)
    14. {}
    15. // all is ok, compiler knows what is QVector<int>, and it has both declarations and
    16. // definitions of all needed SSVector methods
    To copy to clipboard, switch view to plain text mode 
    I hope it helps.
    Last edited by stampede; 19th June 2011 at 22:31. Reason: typo

  15. The following user says thank you to stampede for this useful post:

    Computer Hater (19th June 2011)

  16. #11
    Join Date
    Nov 2010
    Posts
    63
    Thanks
    26
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Writing a QVector subclass

    Thank you for the effort of explaining it, stampede. :b
    I'm afraid I lack some combination of knowledge and the proper conception right now. I hope it will become clearer to me over time.

  17. #12
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Writing a QVector subclass

    Quote Originally Posted by Computer Hater View Post
    I'm not yet experienced enough to understand why that matters. Didn't have it come up before. I will give it some thought.
    Basically, it is too easy to create bugs and memory leaks by not releasing objects you think are being released. For instance, if you create variables or objects in your constructor or elsewhere, don't assume that your destructor will get called to release them.

    If you are just adding methods which are stateless, then there is typically no reason to subclass vector.

    But in the end it is your code and you are of course free to code it how you like

  18. The following user says thank you to squidge for this useful post:

    Computer Hater (20th June 2011)

  19. #13
    Join Date
    Nov 2010
    Posts
    63
    Thanks
    26
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Writing a QVector subclass

    I just did a little experiment with inheritance and virtual desctructors and I think I get what you mean.
    It seems that QVector still has no virtual destructor, as you said, telling from the result I got. (And from the source code, now that I think of it ;-))
    So I think I get the importance of that part. Thank you for the warning, the relevance of which I missed the first time around.
    For this and other reasons, I think I will use a non-inherited template class instead.

    If I may trouble you some more, could you give me a quick idea of what a "stateless method" is ?
    I'm not familiar with the term. I googled it, but without knowing more context, it's hard to read the right hits or use the right search terms.

  20. #14
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Writing a QVector subclass

    a "Stateless method" is just that - a method which retains no state between calls. For example, if you subclassed QVector to add a "find" method rather than just using find of std::algorithm (ie, std::find(x.begin(), x.end(), v) != x.end()) that would be a stateless method as no information (state) is stored between calls.

Similar Threads

  1. QVector, QLinkedList
    By aash_89 in forum Qt Programming
    Replies: 2
    Last Post: 22nd July 2010, 02:20
  2. Replies: 8
    Last Post: 12th February 2010, 02:41
  3. Qvector
    By phillip_Qt in forum Qt Programming
    Replies: 3
    Last Post: 27th November 2007, 10:46
  4. QVector
    By sabeesh in forum Qt Programming
    Replies: 2
    Last Post: 17th September 2007, 14:37
  5. Subclass
    By merry in forum General Programming
    Replies: 2
    Last Post: 1st March 2007, 10:34

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.