Why Is Important to Include ".Moc" File at End of a Qt Source Code File

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:

  1. qmake must generate rules inside your Makefile to invoke moc on that .cpp file.

    That special (hackish?) inclusion triggers qmake to do so, and tells it which would be moc's output file (teststring.moc) when invoked on your .cpp.

  2. 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 as YourClass::staticMetaObject and similar, because it has no idea that YourClass 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 means moc's output can be happily compiled.

    But what if your class definition is inside a .cpp? You can't #include a .cpp file in moc'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 means qmake will only emit one rule saying to run moc, but not another rule telling the compiler to compile moc'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



Leave a reply



Submit