简体   繁体   中英

How to subclass QVector?

I have a class named Symbol and I would like to create a QVector subclass (Symbols) to add some useful methods. But when I use Symbols from another class A, the compiler gives the error 'Symbols does not name a type'.

class Symbols: public QVector< Symbol >
{
public:
    Symbols() {}

    // Useful methods
    QSymbol findSymbol(const QString &name);

    // ...
};

class A
{
private:
    Symbols symbols;
};

Is it correctly subclassed?

Why appears 'Symbols does not name a type' when compiles class A?

It's usually ill advised to derive from a container. You almost always want a "Has A" relationship otherwise your class will expose members that users of your class can use which may corrupt the state.

Also it looks like you're trying to implement a look up in your class which means perhaps QMap or QHash would be a more appropriate container

After these comments, I must add this to the answer. Don't inherit from QVector<T> . That type doesn't have virtual destructor, and the most important thing in the inheritance ( IS-A ) relationship will be broken in that case.

Look into your class Symbols, and imagine you've over time increased complexity of it, so now you have destructor and constructor somewhere:

class Symbols: public QVector<Symbol>
{
    ~Symbols()
    {
        important_cleanup_here();
    }
};

You might think that Symbols is a subtype of QVector<Symbol> , so one of your clients write something like this:

QVector<Symbol>* symbols = new Symbols(); 

Sound good, right? After all, Symbols extends QVector<Symbol> , so it can follow substitute principle, right? Wrong. Because QVector<T> destructor is not virtual, this will not call Symbols destructor!

delete symbols;

Worse than that, this is undefined behavior and compiler could do whatever he feels like.

If you just want convenient method, create a non-method which will do the trick for you

QSymbol findSymbol(const QVector<QSymbol>&, const QString& name);

(for the reference on this, read this amazing Scott Meyer's article: http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197 )

In your example, of course, there's nothing to be scared of. But why putting such a burden on one of your classes, when you can use composition without any fear?

Also, refer to this (and few others) reported bug on this: https://bugreports.qt.io/browse/QTBUG-8292

Other than all other problems, I can see one right here:

class Symbols: public QVector<Symbol>
{
      QSymbol findSymbol(const QString &name);
};

Based on what I see, it should be either

class Symbols: public QVector<Symbol>
{
      Symbol findSymbol(const QString &name);
};

or

class Symbols: public QVector<QSymbol>
{
      QSymbol findSymbol(const QString &name);
};

I found it!

The problem was that I had a circular dependence.

Class Symbols:

#ifndef SYMBOLS_H
#define SYMBOLS_H
#include <QVector>
#include "A.h"
#include "symbol.h"

class Symbols: public QVector<Symbol>
{
public:
    Symbols() {}
};
#endif // SYMBOLS_H

Class A:

#include "symbols.h"
class A {
   private:
     QSymbols symbols;
}

The #include "Ah" provokes the error. It was there because I had a function with a reference to the class A. I must to search how to resolve circular references :).

Thank you very much to everyone.

You are having a couple of issues why your code does not compile:

  • Missing the semi-colons after the class declarations, provided they are in the same file. Failing that, you would of course need to include the header file containing the Symbol's declaration into your file using it.

  • You are using QSymbol return value instead of Symbol.

  • You are not including QVector.

Here is a compiling code.

main.cpp

#include <QVector>

class Symbol
{
};

class Symbols: public QVector<Symbol>
{
    public:
      Symbols() {}

      Symbol findSymbol(const QString &name) {}
};


class A {
       Symbols symbols;
};

int main()
{
    return 0;
}

main.pro

TEMPLATE = app
TARGET = main
QT = core
SOURCES += main.cpp

Build

qmake && (n)make

That being said, QSymbol looks fishy, too, as there is no such a class in Qt, and you really should not take names like that since that only causes confusion. Also, starting all the classes with a prefix is just silly, and only around in Qt for compatibility reasons, not because it is better than namespaces.

Also, please do not buy the argument that it is ultimately a bad idea to subclass containers. QStringList is a good example to prove that claim wrong.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM