2016-09-01 4 views
5

Qt는 객체 통신에 signals and slots을 사용합니다. 신호은 일반적으로 멤버 함수로 선언되므로 Qt MOC는 해당 함수의 정의를 생성합니다.Qt 신호가 const가 아닌 이유

신호가 const 멤버 함수가 아닌 이유는 무엇입니까?

편집 : 나는 신호가 발신자를 변경하지 않을 것으로 기대할 것이므로 그것이 그 이유 다.

+2

왜 'const'가되어야한다고 생각하십니까? –

+1

@CaptainObvlious : 그들은 보내는 인스턴스를 변경하지 않습니까? –

+0

@BenVoigt 나도 몰라. 그래서 내가 묻는거야. –

답변

7

내가 신호 (generated by the MOC으로) 보낸 사람에게

신호를 수정하지 기대 직접 클래스 인스턴스의 멤버를 수정하지 않습니다. 그러나 생성 된 코드는 (잠재적 인) 슬롯에 의해 소비되도록 this 포인터를 따라 전달됩니다. 따라서 연결된 슬롯은 신호 발신자를 변경시킬 수 있습니다.

기술적 인 이유는 신호가 const 인 경우 모든 슬롯 구현이 코드를 오류없이 컴파일하기 위해 발신자에게 const 클래스 구성원 만 호출해야한다는 것입니다.

코드가 아닌 안전성과 관련하여 신호를 const 클래스 멤버로 구현하는 것은 이해할 수있는 결정입니다. 많은 경우 (예 : 동일한 클래스에 구현 된 연결된 슬롯이 const 인 경우 또는 연결된 슬롯이 다른 개체에 모두 속한 경우) 부 자연스러운 것으로 느껴집니다.

+1

"모든 슬롯 구현은 또한 const 여야합니다 "- 아니요, 이것은 송신자 객체에 대한 포인터를받는 매개 변수가 암시적인 this 변수가 아닌'const' 적격이어야한다는 것을 의미합니다. –

+0

@BenVoigt : 맞습니다. 이것은 신호와 슬롯이 동일한 클래스에서 구현된다는 가정하에 작성되었습니다. 이것은 필수 사항은 아니며, 실제로는 종종 그렇지 않습니다. – IInspectable

+0

같은 클래스에 구현 되더라도, 당신의 요지가 잘못되었다고 생각합니다. 이것을 시도해 보셨습니까? 그렇다면 어떤 Qt 버전을 사용합니까? 내 대답에서 만든 시험을 보아라. – ymoreau

0

Qt 신호가 const AFAIK (Qt5.9에서 테스트 됨)이되는 것을 방지하지 못합니다. 대답은입니다. 올바르지 않습니다. 이하

제가 그것이
여전히 가능 표시하게 테스트이다 - 동일한 인스턴스
비 CONST 슬롯CONST 신호 연결 - 온 const가 아닌 방법을 전화 sender().

미세 (GCC)를 컴파일 내 테스트의 클래스 : 여기

// Stupid class to test the emit of a const-signal 
class Test : public QObject 
{ 
    Q_OBJECT 

public: 
    // Connect in the constructor from this instance to this instance 
    explicit Test(QObject *parent = nullptr) : QObject(parent) { 
     connect(this, &Test::valueChanged, this, &Test::updateString); 
    } 

    // To test a non-const method call 
    void nonConstFoo() { 
     setObjectName("foo"); // I modify the 'this' instance 
    } 

    // To test emit of a non-const signal from a const-method 
// void constFoo() const { 
//  emit fooSignal(); // --> FAIL at compile time 
// } 

public slots: 
    void setValue(int value) { 
     m_value = value; 
     emit valueChanged(value); 
    } 

    void updateString(int value) { 
     m_string = QString::number(value); // I modify the 'this' instance 
     nonConstFoo(); // I modify the 'this' instance through a non-const call 

     auto s = sender(); 
     s->setObjectName("mutated name"); // I modify the 'sender' instance 

     qDebug() << "Updated string" << m_string; 
    } 

signals: 
    void valueChanged(int) const; // The signal is const 
    void fooSignal(); // Non-const signal 

private: 
    int m_value; 
    QString m_string; 
}; 

그리고는 신호의 MOC에 의해 생성 된 코드 :

// SIGNAL 0 
void Test::valueChanged(int _t1)const 
{ 
    void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) }; 
    QMetaObject::activate(const_cast< Test *>(this), &staticMetaObject, 0, _a); 
} 

// SIGNAL 1 
void Test::fooSignal() 
{ 
    QMetaObject::activate(this, &staticMetaObject, 1, nullptr); 
} 

우리가 볼 수있는 Qt를 사용하는 것을 const_cast 이 있습니다. 이렇게 모든 것이 어쨌든 작동합니다. 제 생각에는


는 신호가 기본적으로에서 const되지 않는 이유는,이 당신의 헤더에 신호 (== 클래스 메소드) 정의를 하는 CONST를 추가 할 MOC를 필요로한다는 것이다 따라서 소스 코드를 수정하십시오.

나는 이것이 신호의 각 정의를 매크로로 묶음으로써 가능할 것이라고 생각하지만, 코더와 독자의 고통을 상상해 보라.나는 당신이 const로 선언 한 신호를 가지고 있다는 Qt (또는 당신)를위한 어떤 이득도 보지 못했고, 이것은 당신과 Qt를 위해서 더 많은 일을 요구할 것입니다.

때때로 const로 선언해야 할 수도 있습니다. 당신이 const 메서드에서 그것들을 내고 싶을 때처럼. 그리고 당신은 자유롭게 그렇게 할 수 있습니다.

+0

'const_cast'를 사용하여'const' 한정자를 버리면됩니다. 한정자를 캐스팅 한 후에 포인터/참조를 통해 객체를 변경하는 것은 정의되지 않은 동작입니다. 일을하는 것은 정의되지 않은 행동의 완벽하게 유효한 형태입니다. 아직 정의되지 않았으며 준수하는 구현은 프로그램의 결과 또는 전체에 대해 ** 아무런 ** 보장을하지 않습니다. – IInspectable

+0

피드백에 대한 Thx, 정의되지 않은 동작의 이러한 사례에 대한 리소스가 있습니까? 나는 이것이 정적 데이터에서 어떻게 문제가 될 수 있는지 알지만 실제로는 Object-pointer가 될 때 왜 그런지는 알지 못합니다. 특히'const_cast'는 MOC에 의해 생성되고'QMetaObject :: activate'는 그 포인터를 사용하여'sender-> d_func()'와 같은 non-const 메쏘드를 명확하게 호출합니다. 나는이'const_cast' 권한을 생성 할 때 Qt-devs가 무엇을하는지 알고 있다고 가정한다. – ymoreau

+0

[\ [expr.const.cast \]] (http://eel.is/c++draft/expr.const.cast) 및 [\ [dcl.type.cv \]] (http : // eel.is/c++draft/dcl.type.cv). 이것은 당신이 어떻게 생각하는지에 관한 것이 아닙니다. C++은 추상 기계로 정의됩니다. 특정 구문을 정의되지 않은 채로두면 컴파일러는 특정 최적화 가능성을 열어 가정을 만들 수 있습니다. * "Qt-devs는 그들이하는 일을 알고 있다고 생각합니다."* - 나는 그것을 믿을만한 이유가 없습니다. – IInspectable

관련 문제