I'm relatively new to Qt, and I am incorporating it into our projects. I made a very small object that inherits QObject that I just use with a timer. I created a header only file for it but realized the compiler quickly didn't like it. So I created a complimentary .cpp file for it to get rid of the errors and it seemed to work.
My question is really, can I create a header only object that inherits QObject and allow it to get automoc'ed? Or will I need to create a complimentary cpp file every time?
I've generated a smaller amount of code to replicate that shows what I mean.
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.11)
# Standardly
set(CMAKE_CXX_STANDARD 11)
# Findn includes in corresponding directories?
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed
set(CMAKE_AUTOMOC ON)
find_package(Qt5Widgets)
add_executable(test Main.cpp)
target_link_libraries(test Qt5::Widgets)
Main.cpp
#include <QApplication>
#include "Header.h"
int main( int argc, char *argv[] )
{
QApplication app( argc, argv );
HeaderOnly();
return( app.exec() );
}
Header.h
#ifndef HEADER_H
#define HEADER_H
#include <QObject>
#include <QTimer>
#include <QDebug>
class HeaderOnly : public QObject
{
Q_OBJECT
public:
HeaderOnly() :
timer_( new QTimer( this ) )
{
QObject::connect( timer_, SIGNAL( timeout() ), this, SLOT( timeout() ) );
timer_->start( 1000 );
}
private slots:
void timeout()
{
qDebug() << "Why hello!";
}
private:
QTimer *timer_;
};
#endif
Output
$ make
[ 25%] Automatic MOC for target test
Generating MOC predefs moc_predefs.h
[ 25%] Built target test_autogen
Scanning dependencies of target test
[ 50%] Building CXX object CMakeFiles/test.dir/Main.cpp.o
[ 75%] Linking CXX executable test
CMakeFiles/test.dir/Main.cpp.o: In function `HeaderOnly::HeaderOnly()':
Main.cpp:(.text._ZN10HeaderOnlyC2Ev[_ZN10HeaderOnlyC5Ev]+0x32): undefined reference to `vtable for HeaderOnly'
CMakeFiles/test.dir/Main.cpp.o: In function `HeaderOnly::~HeaderOnly()':
Main.cpp:(.text._ZN10HeaderOnlyD2Ev[_ZN10HeaderOnlyD5Ev]+0xf): undefined reference to `vtable for HeaderOnly'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/test.dir/build.make:124: test] Error 1
make[1]: *** [CMakeFiles/Makefile2:68: CMakeFiles/test.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
Of course adding this Header.cpp to the source will eliminate the error:
#include "Header.h"
#include "moc_Header.cpp"
There are two solutions:
Include the header file explicitly in the project, just as you would in the .pro
file:
add_executable(test "Main.cpp" "Header.h")
Add the #include "moc_Header.cpp"
in any one (and only one) of the .cpp
files, e.g. in Main.cpp
:
// Main.cpp
...
#include "moc_Header.cpp"
If you get a CMP0071
policy warning when you do that - it's spurious. You need to remove the build folder and re-run cmake to reconfigure the build.