Как создать подкласс QVector?

У меня есть класс с именем Symbol, и я хотел бы создать подкласс QVector (Symbols), чтобы добавить некоторые полезные методы. Но когда я использую символы из другого класса A, компилятор выдает ошибку «Символы не называют тип».

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

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

// ...
};

class A
{
private:
Symbols symbols;
};

Это правильно подкласс?

Почему появляется сообщение «Символы не называют тип» при компиляции класса A?

-1

Решение

Обычно не рекомендуется выводить из контейнера. Вы почти всегда хотите иметь отношение «Имеет A», иначе ваш класс будет выставлять членов, которые могут использовать пользователи вашего класса, что может повредить состояние.

Также похоже, что вы пытаетесь реализовать поиск в своем классе, что означает, что, возможно, QMap или QHash будут более подходящим контейнером

9

Другие решения

После этих комментариев я должен добавить это к ответу. Не наследуй от QVector<T>. Этот тип не имеет виртуального деструктора, а самое главное в наследовании (IS-A) отношения будут нарушены в этом случае.

Посмотрите на свой класс Symbols и представьте, что со временем вы увеличили его сложность, так что теперь у вас есть где-то деструктор и конструктор:

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

Вы можете подумать, что Symbols это подтип QVector<Symbol>Итак, один из ваших клиентов напишет что-то вроде этого:

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

Звучит хорошо, правда? В конце концов, Symbols продолжается QVector<Symbol>Так что это может следовать принципу замены, верно? Неправильно. Так как QVector<T> деструктор не является виртуальным, это не будет называть Symbols деструктор!

delete symbols;

Хуже того, это неопределенное поведение, и компилятор может делать все, что ему хочется.

Если вы просто хотите использовать удобный метод, создайте не метод, который поможет вам

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

(для справки, прочитайте эту удивительную статью Скотта Мейера: 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);
};
4

Я нашел это!

Проблема была в том, что у меня была круговая зависимость.

Символы класса:

#ifndef SYMBOLS_H
#define SYMBOLS_H
#include <QVector>
#include "A.h"#include "symbol.h"
class Symbols: public QVector<Symbol>
{
public:
Symbols() {}
};
#endif // SYMBOLS_H

Класс А:

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

#Include «A.h» провоцирует ошибку. Это было там, потому что у меня была функция со ссылкой на класс А. Я должен искать, как разрешать циклические ссылки :).

Большое спасибо всем.

1

У вас есть пара проблем, почему ваш код не компилируется:

  • Отсутствует точка с запятой после объявлений класса, если они находятся в одном файле. Если это не удастся, вам, конечно, потребуется включить заголовочный файл, содержащий объявление Symbol, в ваш файл, используя его.

  • Вы используете возвращаемое значение QSymbol вместо Symbol.

  • Вы не включая QVector.

Вот код компиляции.

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

строить

qmake && (n)make

Тем не менее, QSymbol также выглядит подозрительно, так как в Qt такого класса нет, и вам действительно не следует брать такие имена, поскольку это только приводит к путанице. Кроме того, начинать все классы с префикса просто глупо, и только в Qt по причинам совместимости, а не потому, что это лучше, чем пространства имен.

Также, пожалуйста, не покупайте аргумент, что в конечном итоге плохая идея создавать подклассы контейнеров. QStringList хороший пример, чтобы доказать, что утверждение неверно.

-1
По вопросам рекламы [email protected]