简体   繁体   English

如何继承QVector?

[英]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. 我有一个名为Symbol的类,我想创建一个QVector子类(Symbols)以添加一些有用的方法。 But when I use Symbols from another class A, the compiler gives the error 'Symbols does not name a type'. 但是,当我使用另一个类A中的Symbols时,编译器给出错误“ Symbols not named 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? 为什么在编译类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. 您几乎总是想要“具有A”关系,否则您的班级将公开班级用户可以使用的成员,这可能会破坏状态。

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 而且看起来您正在尝试在类中实现查找,这意味着QMap或QHash可能是更合适的容器

After these comments, I must add this to the answer. 这些评论之后,我必须将此添加到答案中。 Don't inherit from QVector<T> . 不要继承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. 该类型没有虚拟析构函数,在这种情况下,继承关系( IS-A )中最重要的部分将被破坏。

Look into your class Symbols, and imagine you've over time increased complexity of it, so now you have destructor and constructor somewhere: 查看您的类Symbols,并想像一下随着时间的流逝,它的复杂性增加了,所以现在在某个地方有析构函数和构造函数:

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: 您可能会认为SymbolsQVector<Symbol>的子类型,因此您的一位客户编写了这样的内容:

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

Sound good, right? 听起来不错吧? After all, Symbols extends QVector<Symbol> , so it can follow substitute principle, right? 毕竟, Symbols扩展了QVector<Symbol> ,所以它可以遵循替代原理,对吗? Wrong. 错误。 Because QVector<T> destructor is not virtual, this will not call Symbols destructor! 由于QVector<T>析构函数不是虚拟的,因此不会调用Symbols析构函数!

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 ) (有关此内容的参考,请阅读Scott Meyer的这篇惊人文章: 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 另外,请参考此(以及其他一些报告)有关此的错误: 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: A类:

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

The #include "Ah" provokes the error. #include“ Ah”引发错误。 It was there because I had a function with a reference to the class A. I must to search how to resolve circular references :). 在那里是因为我有一个对类A的引用的函数。我必须搜索如何解析循环引用:)。

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. 失败的话,您当然需要将包含Symbol声明的头文件包含在使用它的文件中。

  • You are using QSymbol return value instead of Symbol. 您正在使用QSymbol返回值而不是Symbol。

  • You are not including QVector. 您不包括QVector。

Here is a compiling code. 这是一个编译代码。

main.cpp 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 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. 话虽这么说,QSymbol也看起来很可疑,因为Qt中没有这样的类,您真的不应该使用这样的名称,因为那样只会引起混乱。 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. 同样,以前缀开头所有类只是愚蠢的,并且仅出于兼容性原因在Qt中开始,而不是因为它比名称空间更好。

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. QStringList是一个很好的例子,证明了声明的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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