QT/Win32 Qt와 C++11
페이지 정보
작성자
본문
최근 대부분의 컴파일러에서 지원하고 있는 C++11의 새로운 기능 중 Qt 에 유용한 것들을 위주로 소개하고자 한다. 따라서 모든 C++11의 항목들을 다루고 있지 않는다.
<b>C++11에 관한 내용은 전문가를 위한 C++(총2권) 이나 C++11 핵심노트등이 국내서로 출판되어 있으니 참고</b>
<b>C++11의 기능 지원하기</b>
일부 컴파일러는 C++11의 지원을 위해 명령행 옵션을 요구하기도 한다. qmake를 빌드 시스템으로 사용중이라면 프로젝트파일에 다음의 라인을 추가한다.
CONFIG += c++11
위 명령행은 Qt 5.1에서 리눅스에서 gcc, Windows에서 Visual Studio, Mac OSX 10.8에서 지원된다.
추가적으로 Qt 5.0.2에서 Mac OSX 10.8을 사용중이라면 아래 라인을 추가하여야 한다.
QMAKE_CXXFLAGS += -std=c++11 -stdlib=libc++ -mmacosx-version-min=10.7
LIBS += -stdlib=libc++ -mmacosx-version-min=10.7
<b>초기화 리스트</b>
c++11의 초기화 리스트는 QStringList 처럼 객체를 초기화 하는데 유용하다.
QStringList fruit;
fruit << "apple" << "pear" << "peach" << "tomato"
는 아래와 같이 작성할 수 있다.
QStringList fruit { "apple", "pear", "peach", "tomato" };
또한 생성자에서 상기와 같은 형태로 맴버변수를 초기화 하고자 하는 경우 초기화 리스트에서 사용이 불가능 하였지만 C++11에서는 가능하게 되었다.
MyClass::MyClass()
{
fruit << "apple" << "pear" << "peach" << "tomato";
}
이렇게 초기화 하던 것을
MyClass:MyClass() : fruit { "apple", "pear", "peach", "tomato" };
{
}
이렇게 표현이 가능하게 되었다.
<b>for 루프</b>
Qt 에서 foreach()를 이용해 for 루프를 편리하게 사용하였었다.
c++11에서는 기본 언어 기능으로 지원이 되어 사용할 수 있게 되었다.
[Qt]
QStringList options { "a", "b", "c", "d" };
foreach (const QString &option, options) {
std::cout << qPrintable(option) << std::endl;
}
[c++11]
QStringList options { "a", "b", "c", "d" };
foreach (const QString &option : options) {
std::cout << qPrintable(option) << std::endl;
}
<b>타입 인터페이스</b>
새로운 타입으로 auto가 추가되었다.
코드로 부터 타입을 유추하는 기능으로 특히 iterator를 선언할 때 아래의 예처럼 유용하다.
[auto 미사용 시]
QList<MyType>::iterator iter = myTypes.begin();
[auto 사용 시]
auto iter = myTypes.begin();
상기의 예(for 루프)는 다음처럼 표현이 가능하다.
QStringList options { "a", "b", "c", "d" };
foreach (auto option : options) {
std::cout << qPrintable(option) << std::endl;
}
auto는 기존 c/c++에도 있던 예약어 였지만 거의 사용되지 않던 예약어였다. 하지만 c++11에서 가장 핫(?)한 예약어가 될 것으로 믿어 의심치 않는다.
<b>새로운 스타일의 connect</b>
Qt 응용프로그램은 런타임에서 connect()를 이용하여 signal/slot의 연결이 매우 많이 사용된다. Qt 개발자들 중 일부는 런타임에서 메시지를 살펴봄으로 써 signal/slot 연결에러를 찾는 방법을 알고 있었다.
디버깅할 때 Application Output창을 보면 잘못 연결된 signal/slot을 출력해준다.
하지만 C++11에서는 런타임이 아닌 컴파일 타임에 이를 체크할 수 있는 새로운 문법을 소개하였다.
connect(button, SIGNAL(clicked()), checkbox, SLOT(toggle())); // 기존 사용방법
은 다음과 같이 쓰여진다.
connect(button, &QPushButton::clicked, checkbos, &QCheckBox::toggle); // 새로운 문법 적용
기존 사용 방법의 문제점은 SIGNAL(), SLOT()에 의한 문자열 확장을 사용하기 때문에 signal과 slot함수의 인자가 서로 맞아야 하는 데 이를 컴파일 타임에 걸러낼 수 없다는 문제점이 있다.
connect(button, SIGNAL(clicked()), checkbox, SLOT(valueChanged(int))); // 잘못된 signal/slot 사용방법이지만 컴파일러는 아무런 문제 없이 컴파일 함.
새로운 스타일의 connect() 에서는 signal/slot의 이름과 인자과 컴파일 타임에 체크가 된다.
문자열이 아닌 함수명으로 직접 타입체크를 하기 때문이다.
물론 기존 형태(SIGNAL(), SLOT() 매크로에 의한 문장열로 확장형태)도 여전히 사용할 수 있다.
또한 c++11에서 람다함수를 slot함수로 사용할 수 있다.
auto mySlot = []() { qDebug() << "this is my slot."; };
connect(button, &QPushButton::clicked, mySlot);
위의 코드를 더 단축하면
connect(button, &QPushButton::clicked, [=]() { qDebug() << "This is my slot."; });
이렇게 표현 가능하다. (람다식 만세)
눈치 챘는지 모르겠지만 람다식을 사용하면 더 이상 slot()함수를 별도로 선언하여 작성하지 않아도 된다.
<b>Threads</b>
C++11에서는 이제 언어차원의 쓰레드와 컨커런트 프로그래밍을 지원한다. 그래픽 관련 코드가 아니라면 이제 언어에서 제공되는 쓰레드와 컨커런트 프로그래밍을 사용하여 이식성을 높일 수 있다.
<b>정규식 표현</b>
C++11의 standard library에서 정규식 표현을 지원한다. Qt5 에서 지원하는 QRegularExpression(Qt4 에서는 QRegExp) 클래스만큼 포관적이진 않지만 thread의 경우처럼 이식성이 중요하고 기능이 사용하기에 충분하다면 사용하는 것이 좋을 것이다.
<b>nullptr 상수</b>
c++11에서는 0, NULL 대신으로 사용하도록 nullptr이라는 새로운 키워드를 추가하였다. 간단한 수정으로 기존값이 묵시적으로 원치않는 형변환이 일어나는 문제를 피할 수 있게 해준다.
[사용예]
char *pc = nullptr; //OK
int *pi = nullptr; //OK
bool bp = nullptr; // OK, nullptr은 flase로 변환
int i = nullptr; // Error, nullptr은 int로 형변환 되지 않음
<b>Right Angle Bracket</b>
템플릿을 사용할 때 '>' 브라켓을 사용하게 되는 데 간혹 연속으로 사용 시 ">>"로 컴파일러가 인식을 하여 에러가 내는 경우가 많아 기존에는 아래와 같은 우스꽝 스런 코드를 사용했었다.
QList<QMap<QString, int> > list;
컴파일러가 충분히 문맥상으로 판단이 가능하지만 (왜 이걸 기존에 문법적으로 에러 처리했는지는 이해가...) 에러 처리 되었던 걸 c++11에서는 이제 당당하게 템플릿에서 >>을 사용할 수 있게 되었다.
QList<QMap<QString, int>> list;
<b>새로운 문자열 리터럴</b>
c++11에서는 세가지 새로운 유니코드 인코딩 포멧과 raw 인코딩이 추가되었다. raw 인코딩은 문자열 내의 ''을 이스케이프 문자로 인식하는 것이 아니라 그대로 ''로 인식한다.
QString s1 = "foo";
QString s2 = R"(foo\bar)";
QString s3 = u8("foo");
QString s4 = u8R"(foo)";
QString s5 = QString::fromUtf16(reinterpret_cast<const ushort *>(u"foo")); // UTF-16
QString s6 = QString::fromUtf16(reinterpret_cast<const ushort *>(uR"(foo)")); // UTF-16 raw
QString s7 = QString::fromUcs4(reinterpret_cast<const uint*>(U"foo")); // UTF-32
QString s8 = QString::fromUcs4(reinterpret_cast<const uint*>(UR"(foo)")); // UTF-32
<b>long long 타입</b>
long long 타입이 c++11에서 정식으로 도입되었다. (64비트 이상의 데이터 형)
더이상 이식을 위해 qlonglong을 사용하지 않아도 된다.
<b>새로운 STL 컨테이너</b>
c++11은 새로운 컨테이너들을 소개하였다. array, foward_list, unordered_map, unordered_multimap, unordered_set, unordered_multiset 등이 그것들인데 Qt 컨테이너들을 사용해도 괜찮지만 이식성을 고려해 이것들을 사용할 수도 있다.
원문 출처 : http://www.ics.com/blog/qt-and-c11#.VDoucvl_sSw
<b>C++11에 관한 내용은 전문가를 위한 C++(총2권) 이나 C++11 핵심노트등이 국내서로 출판되어 있으니 참고</b>
<b>C++11의 기능 지원하기</b>
일부 컴파일러는 C++11의 지원을 위해 명령행 옵션을 요구하기도 한다. qmake를 빌드 시스템으로 사용중이라면 프로젝트파일에 다음의 라인을 추가한다.
CONFIG += c++11
위 명령행은 Qt 5.1에서 리눅스에서 gcc, Windows에서 Visual Studio, Mac OSX 10.8에서 지원된다.
추가적으로 Qt 5.0.2에서 Mac OSX 10.8을 사용중이라면 아래 라인을 추가하여야 한다.
QMAKE_CXXFLAGS += -std=c++11 -stdlib=libc++ -mmacosx-version-min=10.7
LIBS += -stdlib=libc++ -mmacosx-version-min=10.7
<b>초기화 리스트</b>
c++11의 초기화 리스트는 QStringList 처럼 객체를 초기화 하는데 유용하다.
QStringList fruit;
fruit << "apple" << "pear" << "peach" << "tomato"
는 아래와 같이 작성할 수 있다.
QStringList fruit { "apple", "pear", "peach", "tomato" };
또한 생성자에서 상기와 같은 형태로 맴버변수를 초기화 하고자 하는 경우 초기화 리스트에서 사용이 불가능 하였지만 C++11에서는 가능하게 되었다.
MyClass::MyClass()
{
fruit << "apple" << "pear" << "peach" << "tomato";
}
이렇게 초기화 하던 것을
MyClass:MyClass() : fruit { "apple", "pear", "peach", "tomato" };
{
}
이렇게 표현이 가능하게 되었다.
<b>for 루프</b>
Qt 에서 foreach()를 이용해 for 루프를 편리하게 사용하였었다.
c++11에서는 기본 언어 기능으로 지원이 되어 사용할 수 있게 되었다.
[Qt]
QStringList options { "a", "b", "c", "d" };
foreach (const QString &option, options) {
std::cout << qPrintable(option) << std::endl;
}
[c++11]
QStringList options { "a", "b", "c", "d" };
foreach (const QString &option : options) {
std::cout << qPrintable(option) << std::endl;
}
<b>타입 인터페이스</b>
새로운 타입으로 auto가 추가되었다.
코드로 부터 타입을 유추하는 기능으로 특히 iterator를 선언할 때 아래의 예처럼 유용하다.
[auto 미사용 시]
QList<MyType>::iterator iter = myTypes.begin();
[auto 사용 시]
auto iter = myTypes.begin();
상기의 예(for 루프)는 다음처럼 표현이 가능하다.
QStringList options { "a", "b", "c", "d" };
foreach (auto option : options) {
std::cout << qPrintable(option) << std::endl;
}
auto는 기존 c/c++에도 있던 예약어 였지만 거의 사용되지 않던 예약어였다. 하지만 c++11에서 가장 핫(?)한 예약어가 될 것으로 믿어 의심치 않는다.
<b>새로운 스타일의 connect</b>
Qt 응용프로그램은 런타임에서 connect()를 이용하여 signal/slot의 연결이 매우 많이 사용된다. Qt 개발자들 중 일부는 런타임에서 메시지를 살펴봄으로 써 signal/slot 연결에러를 찾는 방법을 알고 있었다.
디버깅할 때 Application Output창을 보면 잘못 연결된 signal/slot을 출력해준다.
하지만 C++11에서는 런타임이 아닌 컴파일 타임에 이를 체크할 수 있는 새로운 문법을 소개하였다.
connect(button, SIGNAL(clicked()), checkbox, SLOT(toggle())); // 기존 사용방법
은 다음과 같이 쓰여진다.
connect(button, &QPushButton::clicked, checkbos, &QCheckBox::toggle); // 새로운 문법 적용
기존 사용 방법의 문제점은 SIGNAL(), SLOT()에 의한 문자열 확장을 사용하기 때문에 signal과 slot함수의 인자가 서로 맞아야 하는 데 이를 컴파일 타임에 걸러낼 수 없다는 문제점이 있다.
connect(button, SIGNAL(clicked()), checkbox, SLOT(valueChanged(int))); // 잘못된 signal/slot 사용방법이지만 컴파일러는 아무런 문제 없이 컴파일 함.
새로운 스타일의 connect() 에서는 signal/slot의 이름과 인자과 컴파일 타임에 체크가 된다.
문자열이 아닌 함수명으로 직접 타입체크를 하기 때문이다.
물론 기존 형태(SIGNAL(), SLOT() 매크로에 의한 문장열로 확장형태)도 여전히 사용할 수 있다.
또한 c++11에서 람다함수를 slot함수로 사용할 수 있다.
auto mySlot = []() { qDebug() << "this is my slot."; };
connect(button, &QPushButton::clicked, mySlot);
위의 코드를 더 단축하면
connect(button, &QPushButton::clicked, [=]() { qDebug() << "This is my slot."; });
이렇게 표현 가능하다. (람다식 만세)
눈치 챘는지 모르겠지만 람다식을 사용하면 더 이상 slot()함수를 별도로 선언하여 작성하지 않아도 된다.
<b>Threads</b>
C++11에서는 이제 언어차원의 쓰레드와 컨커런트 프로그래밍을 지원한다. 그래픽 관련 코드가 아니라면 이제 언어에서 제공되는 쓰레드와 컨커런트 프로그래밍을 사용하여 이식성을 높일 수 있다.
<b>정규식 표현</b>
C++11의 standard library에서 정규식 표현을 지원한다. Qt5 에서 지원하는 QRegularExpression(Qt4 에서는 QRegExp) 클래스만큼 포관적이진 않지만 thread의 경우처럼 이식성이 중요하고 기능이 사용하기에 충분하다면 사용하는 것이 좋을 것이다.
<b>nullptr 상수</b>
c++11에서는 0, NULL 대신으로 사용하도록 nullptr이라는 새로운 키워드를 추가하였다. 간단한 수정으로 기존값이 묵시적으로 원치않는 형변환이 일어나는 문제를 피할 수 있게 해준다.
[사용예]
char *pc = nullptr; //OK
int *pi = nullptr; //OK
bool bp = nullptr; // OK, nullptr은 flase로 변환
int i = nullptr; // Error, nullptr은 int로 형변환 되지 않음
<b>Right Angle Bracket</b>
템플릿을 사용할 때 '>' 브라켓을 사용하게 되는 데 간혹 연속으로 사용 시 ">>"로 컴파일러가 인식을 하여 에러가 내는 경우가 많아 기존에는 아래와 같은 우스꽝 스런 코드를 사용했었다.
QList<QMap<QString, int> > list;
컴파일러가 충분히 문맥상으로 판단이 가능하지만 (왜 이걸 기존에 문법적으로 에러 처리했는지는 이해가...) 에러 처리 되었던 걸 c++11에서는 이제 당당하게 템플릿에서 >>을 사용할 수 있게 되었다.
QList<QMap<QString, int>> list;
<b>새로운 문자열 리터럴</b>
c++11에서는 세가지 새로운 유니코드 인코딩 포멧과 raw 인코딩이 추가되었다. raw 인코딩은 문자열 내의 ''을 이스케이프 문자로 인식하는 것이 아니라 그대로 ''로 인식한다.
QString s1 = "foo";
QString s2 = R"(foo\bar)";
QString s3 = u8("foo");
QString s4 = u8R"(foo)";
QString s5 = QString::fromUtf16(reinterpret_cast<const ushort *>(u"foo")); // UTF-16
QString s6 = QString::fromUtf16(reinterpret_cast<const ushort *>(uR"(foo)")); // UTF-16 raw
QString s7 = QString::fromUcs4(reinterpret_cast<const uint*>(U"foo")); // UTF-32
QString s8 = QString::fromUcs4(reinterpret_cast<const uint*>(UR"(foo)")); // UTF-32
<b>long long 타입</b>
long long 타입이 c++11에서 정식으로 도입되었다. (64비트 이상의 데이터 형)
더이상 이식을 위해 qlonglong을 사용하지 않아도 된다.
<b>새로운 STL 컨테이너</b>
c++11은 새로운 컨테이너들을 소개하였다. array, foward_list, unordered_map, unordered_multimap, unordered_set, unordered_multiset 등이 그것들인데 Qt 컨테이너들을 사용해도 괜찮지만 이식성을 고려해 이것들을 사용할 수도 있다.
원문 출처 : http://www.ics.com/blog/qt-and-c11#.VDoucvl_sSw
Qt !!!
추천1
관련링크
댓글목록
인라이너님의 댓글

감사합니다
harunene님의 댓글

람다식 만세!