Как правильно использовать qRegisterMetaType в классе, производном от QObject?

Я долго и широко искал ответ на этот вопрос, но но безрезультатно. Я сожалею о следующем:

У меня есть ClassA , который примерно выглядит так:

class ClassA : public QObject {
    Q_OBJECT
public:
    ClassA() { mName = "lol"; }
    ~ClassA();
    void ShowName() { std::cout << mName << std::endl; }
    std::string mName;
};

Конечно, поскольку я использую moc, этот класс фактически разделен на cpp и hpp в моем проекте, но это часть здесь не проблема.

Обратите внимание, что я не использую Q_DECLARE_METATYPE специально, потому что мне прямо сейчас не нужны его возможности (расширение QVariant). Меня интересует только создание экземпляра во время выполнения.

Проблема в том, что Q_OBJECT запрещает конструкторы копирования и присваивания.Из-за этого я должен применить qRegisterMetaType не к самому ClassA , а к ClassA * , который, на первый взгляд, работает нормально.

Теперь я хочу создать этот класс динамически во время выполнения из строки и запустить метод ShowName () . Я делаю это примерно так:

int main() {
    qRegisterMetaType<ClassA*>("ClassA*");

    int id = QMetaType::type("ClassA*");
    std::cout << "meta id: " << id << std::endl; // Outputs correct generated user id (not 0)

    ClassA* myclass = static_cast<ClassA*>(QMetaType::construct(id));
    myclass->ShowName(); // Segfaults, oh dear

    return 0;
}

Вот и моя проблема. Кажется, у меня там нет правильно сконструированного объекта.

Если мы изменим класс так, чтобы он выглядел так:

class ClassA : public QObject {
    Q_OBJECT
public:
    ClassA() { mName = "lol"; }
    ClassA(const ClassA& other) { assert(false && "DONT EVER USE THIS"); }
    ~ClassA();
    void ShowName() { std::cout << mName << std::endl; }
    std::string mName;
};

, то мы можем изменить нашу программу соответственно на:

int main() {
    qRegisterMetaType<ClassA>("ClassA");

    int id = QMetaType::type("ClassA");
    std::cout << "meta id: " << id << std::endl; // Outputs correct generated user id (not 0)

    ClassA* myclass = static_cast<ClassA*>(QMetaType::construct(id));
    myclass->ShowName(); // "lol", yay

    return 0;
}

Очевидно, я мог бы просто использовать мой поддельный конструктор перезаписанной копии, но это кажется неправильным, и Qt предлагает против этого и вместо этого предлагает использовать указатели только на QObject.

Кто-нибудь видит, что здесь не так? Кроме того, я знаю, что есть похожие вопросы по SO, но ни один из них не решает эту точную проблему.

24
задан svenstaro 24 October 2011 в 07:45
поделиться