QObject::connect error: function is used but not defined in this translation unit...
-
I try to connect signal in MainWindow class with slot in GraphicsScene, but during compilation occurs an error: function 'GraphicsScene::ToolSelected' is used but not defined in this translation unit, and cannot be defined in any other translation unit because its type does not have linkage. Here is simplified code:
#include <QtWidgets> #include "Globals.h" #include "ImageLayer.h" class GraphicsScene : public QGraphicsScene { Q_OBJECT friend class MainWindow; public slots: void ToolSelected(ActiveTool activeTool); };
#include <QtWidgets> #include "Canvas.h" #include "LayerPreview.h" #include "Globals.h" #include "GraphicsScene.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT signals: void ToolSelected(ActiveTool activeTool); };
Some MainWindow's function:
... graphicsScene = QSharedPointer<GraphicsScene>(new GraphicsScene(this)); graphicsScene->setSceneRect(0, 0, width, height); connect(this, &MainWindow::ToolSelected, graphicsScene, &GraphicsScene::ToolSelected); ...
How to fix it?
-
I try to connect signal in MainWindow class with slot in GraphicsScene, but during compilation occurs an error: function 'GraphicsScene::ToolSelected' is used but not defined in this translation unit, and cannot be defined in any other translation unit because its type does not have linkage. Here is simplified code:
#include <QtWidgets> #include "Globals.h" #include "ImageLayer.h" class GraphicsScene : public QGraphicsScene { Q_OBJECT friend class MainWindow; public slots: void ToolSelected(ActiveTool activeTool); };
#include <QtWidgets> #include "Canvas.h" #include "LayerPreview.h" #include "Globals.h" #include "GraphicsScene.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT signals: void ToolSelected(ActiveTool activeTool); };
Some MainWindow's function:
... graphicsScene = QSharedPointer<GraphicsScene>(new GraphicsScene(this)); graphicsScene->setSceneRect(0, 0, width, height); connect(this, &MainWindow::ToolSelected, graphicsScene, &GraphicsScene::ToolSelected); ...
How to fix it?
@clostridium_difficile said in QObject::connect error: function is used but not defined in this translation unit...:
How to fix it?
Define void ToolSelected(ActiveTool activeTool)
So, do you havevoid GraphicsScene::ToolSelected(ActiveTool activeTool) { }
somewhere?
Also, why do you define MainWindow as friend in GraphicsScene?
-
It is defined already. Error still occurs. MainWindow is friend of GraphicsScene since... well, it needs access to private member functions of GraphicsScene.
-
It is defined already. Error still occurs. MainWindow is friend of GraphicsScene since... well, it needs access to private member functions of GraphicsScene.
@clostridium_difficile said in QObject::connect error: function is used but not defined in this translation unit...:
It is defined already
Can you show the definition? And do you actually build/link the cpp files where the definition is?
-
It is defined already. Error still occurs. MainWindow is friend of GraphicsScene since... well, it needs access to private member functions of GraphicsScene.
@clostridium_difficile Maybe a silly question, but is
ActiveTool
a registered type? -
@clostridium_difficile said in QObject::connect error: function is used but not defined in this translation unit...:
It is defined already
Can you show the definition? And do you actually build/link the cpp files where the definition is?
Maybe a silly question, but is
ActiveTool
a registered type?What does it exacly mean? ActiveTool's declaration is in file "Globals.h":
#pragma once namespace { enum class ActiveTool { None, PenTool, MoveTool }; }
-
Maybe a silly question, but is
ActiveTool
a registered type?What does it exacly mean? ActiveTool's declaration is in file "Globals.h":
#pragma once namespace { enum class ActiveTool { None, PenTool, MoveTool }; }
@clostridium_difficile said in QObject::connect error: function is used but not defined in this translation unit...:
What does it exacly mean? ActiveTool's declaration is in file "Globals.h":
I you want to use QObject::connect() all arguments type must be registred to Qt with
qRegisterMetaType<>()
A far as I know, this is mandatory. -
@clostridium_difficile said in QObject::connect error: function is used but not defined in this translation unit...:
What does it exacly mean? ActiveTool's declaration is in file "Globals.h":
I you want to use QObject::connect() all arguments type must be registred to Qt with
qRegisterMetaType<>()
A far as I know, this is mandatory.@KroMignon said in QObject::connect error: function is used but not defined in this translation unit...:
A far as I know, this is mandatory.
For queued connections, not for direct connections.
@clostridium_difficile said in QObject::connect error: function is used but not defined in this translation unit...:
What does it exacly mean? ActiveTool's declaration is in file "Globals.h":
Remove the anonymous namespace, and try again.
-
@KroMignon said in QObject::connect error: function is used but not defined in this translation unit...:
A far as I know, this is mandatory.
For queued connections, not for direct connections.
@clostridium_difficile said in QObject::connect error: function is used but not defined in this translation unit...:
What does it exacly mean? ActiveTool's declaration is in file "Globals.h":
Remove the anonymous namespace, and try again.
@kshegunov said in QObject::connect error: function is used but not defined in this translation unit...:
For queued connections, not for direct connections.
Yes, but as far as I can see, the connect is not forced as Qt::DirectConnection.
If you don't want to have trouble, my suggestion would be to change the function signature to int and cast the int to your enum inside the function:
class MainWindow : public QMainWindow { Q_OBJECT signals: void ToolSelected(int); }; void GraphicsScene::ToolSelected(int activeTool) { ActiveTool at = ActiveTool(activeTool); ... }
-
@kshegunov said in QObject::connect error: function is used but not defined in this translation unit...:
For queued connections, not for direct connections.
Yes, but as far as I can see, the connect is not forced as Qt::DirectConnection.
If you don't want to have trouble, my suggestion would be to change the function signature to int and cast the int to your enum inside the function:
class MainWindow : public QMainWindow { Q_OBJECT signals: void ToolSelected(int); }; void GraphicsScene::ToolSelected(int activeTool) { ActiveTool at = ActiveTool(activeTool); ... }
@KroMignon said in QObject::connect error: function is used but not defined in this translation unit...:
Yes, but as far as I can see, the connect is not forced as Qt::DirectConnection.
True enough. However the connect is between widgets, and these always must live in the main thread, so the connection is a direct one.
If you don't want to have trouble, my suggestion would be to change the function signature to int and cast the int to your enum inside the function:
I disagree. This breaks type-safety for no good reason.
-
@kshegunov said in QObject::connect error: function is used but not defined in this translation unit...:
For queued connections, not for direct connections.
Yes, but as far as I can see, the connect is not forced as Qt::DirectConnection.
If you don't want to have trouble, my suggestion would be to change the function signature to int and cast the int to your enum inside the function:
class MainWindow : public QMainWindow { Q_OBJECT signals: void ToolSelected(int); }; void GraphicsScene::ToolSelected(int activeTool) { ActiveTool at = ActiveTool(activeTool); ... }
@KroMignon said in QObject::connect error: function is used but not defined in this translation unit...:
as far as I can see, the connect is not forced as Qt::DirectConnection
Qt::DirectConnection is used by default when connecting two objects that live in the same thread: https://doc.qt.io/qt-5/qt.html#ConnectionType-enum
my suggestion would be to change the function signature to int and cast the int to your enum inside the function
void GraphicsScene::ToolSelected(int activeTool) { ActiveTool at = ActiveTool(activeTool); ... }
I would not do this, for many reasons:
- It breaks type safety as @kshegunov said. In other words, it defeats the whole purpose of
enum class
which is to improve type safety in enums. - It is good practice to avoid C-style casts whenever possible. Let's take extra care to avoid introducing bad practices to new C++ programmers, especially when more robust alternatives exist.
- There is a solution that does not require breaking type safety, does not require casting, and ultimately cleans up the code: Just remove the
namespace
as @kshegunov said. It is a good idea to remove the namespace anyway because anonymous namespaces should usually not be used in headers.
- It breaks type safety as @kshegunov said. In other words, it defeats the whole purpose of