Why is important to include .moc file at end of a Qt Source code file?
It's necessary if you define QObject
subclasses with the Q_OBJECT
macro in a .cpp
file. When you do so:
qmake
must generate rules inside yourMakefile
to invokemoc
on that.cpp
file.That special (hackish?) inclusion triggers
qmake
to do so, and tells it which would bemoc
's output file (teststring.moc
) when invoked on your.cpp
.In order to compile
moc
's output (which is still a bunch of C++ code) the compiler must see your class definition. Otherwise, it will complain that there's no such thing asYourClass::staticMetaObject
and similar, because it has no idea thatYourClass
exists.Typically one defines classes featuring
Q_OBJECT
in a header file.moc
then adds a#include "header.h"
into its generated output, and this meansmoc
's output can be happily compiled.But what if your class definition is inside a
.cpp
? You can't#include
a.cpp
file inmoc
's output, as that would give you tons of redefinition errors.Instead, you
#include
moc
's output in your.cpp
, so that it gets compiled together and everyone is happy. (This meansqmake
will only emit one rule saying to runmoc
, but not another rule telling the compiler to compilemoc
's output.)
From 2. you can also also desume that defining classes with Q_OBJECT
in a .h
does not require any special inclusion.
When do I have to include moc*.cpp in Qt?
The moc’ed file contains the implementation of the meta object, the signal-slot sugar and few other things. It means that if you compile it more than once you will have duplicated symbols on linking stage.
Actually your best option would be to not include the moc’ed file and add it as other normal compilation unit of your project. It simplifies your code, prevents linkage errors, and have a good impact in your compilation time when implementation files are modified.
Nevertheless, if you decide to include the moc’ed file manually you have to do it only in one place to prevent the aforementioned duplicated implementations.
Another case where a direct include is useful for expressiveness is when you declare a class with the Q_OBJECT
in a .cpp file: including the moc’ed in the same file is coherent with the fact that such class belongs to only that file.
Qt moc_file issues
Whenever I have MOC problems, I Build->Clean All and then Build->Run qmake (Qt Creator IDE). If that doesn't solve my problem, I go into my project folder and delete moc_* files and any other junk that Clean doesn't remove - basically leaving nothing but headers, source and resources.
Issue generating MOC files for QT using a makefile
I finally fixed it.As @G.M. suggested in the comments, probably an implicit rule is executing so i decided to write my own to avoid that.
I added this:
$(BUILD)/%.moc.o: $(BUILD)/%.moc.cpp
@echo COMPILING MOC $<
@mkdir -p $(subst /,\,$(dir $@))
@$(CC) $(CFLAGS) -M -MT $@ -o $(patsubst %.o, %.d, $@) $<
@$(CC) $(CFLAGS) -o $@ -c $<
and everything works fine.
The complete makefile:
BUILD = Build
### SOURCES ###
SRC = Src/Main\
Src/DialogBox/DialogBox
### MOC SOURCES ###
MOC_SRC = Src/DialogBox/DialogBox
### OBJECTS ###
OBJ = $(addsuffix .o, $(addprefix $(BUILD)/, $(SRC)))
OBJ += $(addsuffix .moc.o, $(addprefix $(BUILD)/, $(MOC_SRC)))
### INCLUDES ###
INC = TOO MANY INCLUDES TO PUT HERE....
### LINKER FLAGS ###
LDFLAGS = -LC:/Qt/5.15.0/mingw81_32/lib
LDLIBS = -lQt5Quick -lQt5PrintSupport -lQt5Qml -lQt5Network -lQt5Widgets -lQt5Gui -lQt5Core
### COMPILER FLAGS
CFLAGS = $(INC)
### COMPILER ###
CC = g++
### QT MOC ###
MOC = moc
all: $(BUILD)/test.exe
$(BUILD)/test.exe: $(OBJ)
@echo LINKING $^
@$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
$(BUILD)/%.o: %.cpp
@echo COMPILING $<
@mkdir -p $(subst /,\,$(dir $@))
@$(CC) $(CFLAGS) -M -MT $@ -o $(patsubst %.o, %.d, $@) $<
@$(CC) $(CFLAGS) -o $@ -c $<
$(BUILD)/%.moc.o: $(BUILD)/%.moc.cpp
@echo COMPILING MOC $<
@mkdir -p $(subst /,\,$(dir $@))
@$(CC) $(CFLAGS) -M -MT $@ -o $(patsubst %.o, %.d, $@) $<
@$(CC) $(CFLAGS) -o $@ -c $<
$(BUILD)/%.moc.cpp: %.h
@echo GENERATING MOC $<
@$(MOC) $< -o $@
-include $(OBJ:.o=.d)
.PHONY: clean
clean:
@echo CLEANING......
@rm -rf $(BUILD)/Src $(BUILD)/test.exe
Why cannot write a QWidget class in the main.cpp?
Add following line to the end of main.cpp and rerun qmake
:
#include "main.moc"
That will invoke moc
tool for your main.cpp. It generates meta-object function definitions for your Widget
class resolving your linker errors when you rebuild.
Related Topics
How to Set Timeout for Std::Cin
Struct Initialization of the C/C++ Programming Language
Differencebetween Set and Unordered_Set in C++
C++:Creating an Array with a Size Entered by the User
How Are Circular #Includes Resolved
G++ Does Not Show a 'Unused' Warning
C++ on X86-64: When Are Structs/Classes Passed and Returned in Registers
Gcc Linker Can't Find Standard Library
How to Validate Input Using Scanf
Why Is the Empty Base Class Optimization (Ebo) Is Not Working in Msvc
Behavior When Dereferencing the .End() of a Vector of Strings
How to Read Files in Sequence from a Directory in Opencv
Alternative Function in iOStream.H for Getch() of Conio.H
Lambda Expressions as Class Template Parameters
Overloaded Functions Are Hidden in Derived Class
Mesh Class Called with Default Constructor Not Working Opengl C++
Is the Data in Nested Std::Arrays Guaranteed to Be Contiguous