-1

我有一个名为 Symbol 的类,我想创建一个 QVector 子类(符号)来添加一些有用的方法。但是当我使用另一个类 A 中的符号时,编译器会给出错误“符号没有命名类型”。

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

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

    // ...
};

class A
{
private:
    Symbols symbols;
};

它是正确的子类吗?

为什么编译A类时会出现'Symbols does not name a type'?

4

4 回答 4

9

通常不建议从容器中派生。你几乎总是想要一个“有 A”的关系,否则你的班级会暴露你班级的用户可以使用的成员,这可能会破坏状态。

此外,您似乎正在尝试在您的类中实现查找,这意味着 QMap 或 QHash 可能是更合适的容器

于 2014-04-10T20:52:44.407 回答
4

在这些评论之后,我必须将其添加到答案中。不要继承自QVector<T>. 该类型没有虚拟析构函数,IS-A在这种情况下继承()关系中最重要的东西将被破坏。

查看您的类符号,并想象您随着时间的推移增加了它的复杂性,所以现在您在某个地方有了析构函数和构造函数:

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

您可能认为这Symbols是 的子类型QVector<Symbol>,因此您的一个客户会这样写:

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

听起来不错,对吧?毕竟Symbolsextends QVector<Symbol>,所以它可以遵循替代原则,对吧?错误的。因为QVector<T>析构函数不是虚拟的,所以这不会调用Symbols析构函数!

delete symbols;

更糟糕的是,这是未定义的行为,编译器可以随心所欲。

如果您只想要方便的方法,请创建一个可以为您解决问题的非方法

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

(有关这方面的参考,请阅读这篇令人惊叹的 Scott Meyer 的文章:http ://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197 )

当然,在你的例子中,没有什么好害怕的。但是,当您可以毫无畏惧地使用作文时,为什么要给您的一个班级带来如此沉重的负担呢?

此外,请参阅此(以及其他少数几个)报告的错误:https ://bugreports.qt.io/browse/QTBUG-8292

除了所有其他问题,我可以在这里看到一个:

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

根据我所看到的,它应该是

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

或者

class Symbols: public QVector<QSymbol>
{
      QSymbol findSymbol(const QString &name);
};
于 2014-04-10T21:05:15.407 回答
1

我找到了!

问题是我有一个循环依赖。

类符号:

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

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

A类:

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

#include "Ah" 会引发错误。它在那里是因为我有一个引用类 A 的函数。我必须搜索如何解决循环引用:)。

非常感谢大家。

于 2014-04-10T21:23:01.790 回答
-1

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.

于 2014-04-10T20:55:45.803 回答