이 페이지에서

문자열 기반 연결과 펑터 기반 연결의 차이점

Qt는 C++에서 시그널-슬롯 연결을 작성하는 두 가지 방법을 제공합니다. 바로 문자열 기반 연결 구문과 펑크터 기반 연결 구문입니다. 두 구문 모두 장단점이 있습니다. 아래 표는 두 구문의 차이점을 요약한 것입니다.

기능문자열 기반펑터 기반
형식 검사실행 시 수행컴파일 시 수행
암시적 타입 변환을 수행할 수 있습니다.아니요예
신호를 람다 표현식에 연결할 수 있습니다.아니요예
신호보다 인수가 더 많은 슬롯에 신호를 연결할 수 있습니다(기본 매개변수 사용).예아니요
C++ 함수를 QML 함수에 연결할 수 있습니다.예아니요

다음 섹션에서는 이러한 차이점을 자세히 설명하고, 각 연결 구문에 고유한 기능을 사용하는 방법을 보여줍니다.

형식 검사 및 암시적 형 변환

문자열 기반 연결은 실행 시점에 문자열을 비교하여 유형 검사를 수행합니다.

다음과 같은 제한 사항이 적용됩니다:

제한 사항이유
연결 오류는 프로그램 실행이 시작된 후에만 감지할 수 있습니다.해당 없음
신호와 슬롯 간에는 암시적 변환을 수행할 수 없습니다.문자열 비교기는 C++ 유형 정보에 접근할 수 없으므로, 정확한 문자열 일치에 의존합니다.
typedef 및 네임스페이스를 해결할 수 없습니다.

반면, 펑터 기반 연결은 컴파일러에 의해 검사됩니다. 컴파일러는 컴파일 시점에 오류를 감지하고, 호환되는 유형 간의 암시적 변환을 허용하며, 동일한 유형의 서로 다른 이름을 인식합니다.

예를 들어, ` int `를 전달하는 신호를 ` double`를 받는 슬롯에 연결하려면 펑터 기반 구문만 사용할 수 있습니다. ` QSlider `는 ` int ` 값을 포함하는 반면, ` QDoubleSpinBox `는 ` double ` 값을 포함합니다. 다음 코드 조각은 이 둘을 동기화하는 방법을 보여줍니다:

    auto slider = new QSlider(this);
    auto doubleSpinBox = new QDoubleSpinBox(this);

    // OK: The compiler can convert an int into a double
    connect(slider, &QSlider::valueChanged,
            doubleSpinBox, &QDoubleSpinBox::setValue);

    // ERROR: The string table doesn't contain conversion information
    connect(slider, SIGNAL(valueChanged(int)),
            doubleSpinBox, SLOT(setValue(double)));

다음 예제는 이름 해결 기능이 부족함을 보여줍니다. QAudioInput::stateChanged()는 "QAudio::State" 유형의 인자로 선언되어 있습니다. 따라서 "State" 가 이미 노출되어 있더라도, 문자열 기반 연결에서는 "QAudio::State"를 반드시 명시해야 합니다. 이 문제는 인자 유형이 연결의 일부가 아니기 때문에 펑터 기반 연결에는 적용되지 않습니다.

    auto audioInput = new QAudioInput(QAudioFormat(), this);
    auto widget = new QWidget(this);

    // OK
    connect(audioInput, SIGNAL(stateChanged(QAudio::State)),
            widget, SLOT(show()));

    // ERROR: The strings "State" and "QAudio::State" don't match
    using namespace QAudio;
    connect(audioInput, SIGNAL(stateChanged(State)),
            widget, SLOT(show()));

    // ...

람다 표현식에 대한 연결 설정

펑터 기반 연결 구문을 사용하면 신호를 람다 표현식(실질적으로 인라인 슬롯)에 연결할 수 있습니다. 이 기능은 문자열 기반 구문에서는 사용할 수 없습니다.

다음 예제에서 TextSender 클래스는 QString 매개변수를 전달하는 textCompleted() 신호를 방출합니다. 클래스 선언은 다음과 같습니다:

class TextSender : public QWidget {
    Q_OBJECT

    QLineEdit *lineEdit;
    QPushButton *button;

signals:
    void textCompleted(const QString& text) const;

public:
    TextSender(QWidget *parent = nullptr);
};

다음은 사용자가 버튼을 클릭할 때 ` TextSender::textCompleted() ` 신호를 발산하는 연결 예시입니다:

TextSender::TextSender(QWidget *parent) : QWidget(parent) {
    lineEdit = new QLineEdit(this);
    button = new QPushButton("Send", this);

    connect(button, &QPushButton::clicked, [=] {
        emit textCompleted(lineEdit->text());
    });

    // ...
}

이 예제에서, QPushButton::clicked()와 TextSender::textCompleted() 의 매개변수가 호환되지 않음에도 불구하고 람다 함수 덕분에 연결이 간단해졌습니다. 반면, 문자열 기반의 구현 방식이라면 불필요한 반복 코드가 추가로 필요했을 것입니다.

참고: 펑터 기반 연결구문은 독립형 함수와 일반 멤버 함수를 포함한 모든 함수에 대한 포인터를 허용합니다. 그러나 가독성을 위해 신호는 슬롯, 람다 표현식 및 다른 신호에만 연결해야 합니다.

C++ 객체를 QML 객체에 연결하기

문자열 기반 구문은 C++ 객체를 QML 객체에 연결할 수 있지만, 펑터 기반 구문은 연결할 수 없습니다. 이는 QML 유형이 런타임에 해결되므로 C++ 컴파일러에서는 사용할 수 없기 때문입니다.

다음 예제에서 QML 객체를 클릭하면 C++ 객체가 메시지를 출력하고, 그 반대의 경우도 마찬가지입니다. 다음은 QML 유형입니다( QmlGui.qml 기준):

Rectangle {
    width: 100; height: 100

    signal qmlSignal(string sentMsg)
    function qmlSlot(receivedMsg) {
        console.log("QML received: " + receivedMsg)
    }

    MouseArea {
        anchors.fill: parent
        onClicked: qmlSignal("Hello from QML!")
    }
}

다음은 C++ 클래스입니다:

class CppGui : public QWidget {
    Q_OBJECT

    QPushButton*button;

signals:
    void cppSignal(const QVariant& sentMsg) const;

public slots:
    void cppSlot(const QString& receivedMsg) const {
        qDebug() << "C++ received:" << receivedMsg;
    }

public:
    CppGui(QWidget*parent = nullptr) : QWidget(parent) {
        button = new QPushButton("Click Me!", this);
        connect(button, &QPushButton::clicked, [=] {
            emit cppSignal("Hello from C++!");
        });
    }
};

다음은 시그널-슬롯 연결을 수행하는 코드입니다:

    auto cppObj = new CppGui(this);
    auto quickWidget = new QQuickWidget(QUrl("QmlGui.qml"), this);
    auto qmlObj = quickWidget->rootObject();

    // Connect QML signal to C++ slot
    connect(qmlObj, SIGNAL(qmlSignal(QString)),
            cppObj, SLOT(cppSlot(QString)));

    // Connect C++ signal to QML slot
    connect(cppObj, SIGNAL(cppSignal(QVariant)),
            qmlObj, SLOT(qmlSlot(QVariant)));

참고: QML의모든 JavaScript 함수는 타입 어노테이션을 사용하지 않는 한, C++의 ` QVariant ` 타입에 매핑되는 ` var ` 타입의 매개변수를 받습니다. 자세한 내용은 QML 메서드 호출을 참조하십시오.

QPushButton 이 클릭되면 콘솔에 'QML received: "Hello from C++!"'이 출력됩니다. 마찬가지로, Rectangle이 클릭되면 콘솔에 'C++ received: "Hello from QML!"'이 출력됩니다.

C++ 객체가 QML 객체와 상호 작용할 수 있는 다른 방법에 대해서는 ‘C++에서 QML 객체와 상호 작용하기’를 참조하십시오.

슬롯에서 기본 매개변수를 사용하여 매개변수가 더 적은 시그널에 연결하기

일반적으로 슬롯의 인자 개수가 시그널의 인자 개수와 같거나 적고, 모든 인자 유형이 호환될 때만 연결이 가능합니다.

문자열 기반 연결 구문은 이 규칙에 대한 해결 방법을 제공합니다. 슬롯에 기본 매개변수가 있는 경우, 해당 매개변수는 신호에서 생략할 수 있습니다. 신호가 슬롯보다 적은 수의 인수를 가지고 발신될 때, Qt는 기본 매개변수 값을 사용하여 슬롯을 실행합니다.

펑터 기반 연결은 이 기능을 지원하지 않습니다.

DemoWidget 라는 클래스가 있고, 이 클래스에 기본 인수를 갖는 printNumber() 슬롯이 있다고 가정해 봅시다:

public slots:
    void printNumber(int number = 42) {
        qDebug() << "Lucky number" << number;
    }

문자열 기반 연결을 사용하면, DemoWidget::printNumber() 는 QApplication::aboutToQuit()에 연결할 수 있습니다. 비록 후자에 인수가 없더라도 말이죠. 펑터 기반 연결을 사용하면 컴파일 시 오류가 발생합니다:

DemoWidget::DemoWidget(QWidget*parent) : QWidget(parent) {

    // OK: printNumber()는 기본값 42로 호출됩니다
    connect(qApp, SIGNAL(aboutToQuit()),
           this, SLOT(printNumber()));

    // 오류: 컴파일러에서 호환되는 인수를 요구합니다
    connect(qApp, &QCoreApplication::aboutToQuit,
           this, &DemoWidget::printNumber);
}

펑크터 기반 구문에서 이러한 제한 사항을 우회하려면, 시그널을 슬롯을 호출하는 람다 함수에 연결하십시오. 위의 " 람다 표현식에 연결하기" 섹션을 참조하십시오.

오버로드된 시그널 및 슬롯 선택

문자열 기반 구문을 사용할 때는 매개변수 유형이 명시적으로 지정됩니다. 그 결과, 오버로드된 시그널이나 슬롯 중 원하는 인스턴스가 모호함 없이 명확하게 결정됩니다.

반면, 펑터 기반 구문을 사용할 때는 연결하려는 오버로드된 신호나 슬롯의 버전을 명시적으로 지정해야 합니다.

예를 들어, ` QLCDNumber `에는 ` display() ` 슬롯의 세 가지 버전이 있습니다:

  • QLCDNumber::display(int)
  • QLCDNumber::display(double)
  • QLCDNumber::display(QString)

int 버전을 QSlider::valueChanged()에 연결하려면 다음 두 가지 구문을 사용할 수 있습니다:

    auto slider = new QSlider(this);
    auto lcd = new QLCDNumber(this);

    // String-based syntax
    connect(slider, SIGNAL(valueChanged(int)),
            lcd, SLOT(display(int)));

    // Functor-based syntax
    connect(slider, &QSlider::valueChanged,
            lcd, qOverload<int>(&QLCDNumber::display));

qOverload(), static_cast 및 람다를 사용하여 오버로드된 시그널 및 슬롯에 연결하는 포괄적인 예제는 ‘오버로드된 시그널 및 슬롯에 연결하기’를 참조하십시오.

qOverload()항목도 참조하십시오 .

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.