如果查看Qt的源码,会发现很多类都会有一个***Private类。这是Qt用于封装私有操作的一种设计模式。
给出一个继承自QObject的Private类具体的实现:
MyClass.h
#include "QObject"
class MyClassPrivate;
class MyClass: public QObject{
Q_OBJECT
public:
MyClass();
~MyClass();
void foo();
void foo2();
private:
Q_DECLARE_PRIVATE(MyClass)
Q_DISABLE_COPY(MyClass)
MyClassPrivate * const d_ptr;
};
MyClassPrivate.h :注意这里继承自QObject
class MyClassPrivate: public QObject{
Q_OBJECT
Q_DECLARE_PUBLIC(MyClass)
public:
MyClassPrivate(MyClass*parent) ;
~MyClassPrivate() ;
void bar();
void bar2();
private:
MyClass * const q_ptr;
};
MyClass.cpp --注意这种形式Private类实现写在了MyClass.cpp中
#include "MyClass.h"
#include "QDebug"
#include "MyClassPrivate.h"
MyClassPrivate::MyClassPrivate(MyClass*parent): q_ptr(parent) {
qDebug()<<"-------init MyClassPrivate---------";
}
MyClassPrivate::~MyClassPrivate() {
}
void MyClassPrivate::bar() {
qDebug()<<"--------MyClassPrivate::bar--------";
}
void MyClassPrivate::bar2() {
Q_Q(MyClass);
qDebug()<<"--------MyClassPrivate::bar2--------";
q->foo2();
}
MyClass::MyClass(): d_ptr(new MyClassPrivate(this)) {
qDebug()<<"--------init MyClass--------";
}
MyClass::~MyClass() {
delete d_ptr;
}
void MyClass::foo() {
qDebug()<<"--------MyClass::foo--------";
Q_D(MyClass);
d->bar();
d->bar2();
}
void MyClass::foo2() {
qDebug()<<"--------MyClass::foo2--------";
}
main.cpp
#include <QCoreApplication>
#include <QDebug>
#include "MyClass.h"
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
qDebug() << "Hello World";
MyClass pub;
pub.foo();
return QCoreApplication::exec();
}
对应CMake目录有两种结构,在CMakeList实现上 针对这两种结构有一点区别
首先是第一种结构:
cmake_minimum_required(VERSION 3.23) project(MyClass) set(CMAKE_CXX_STANDARD 14) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) #set(CMAKE_PREFIX_PATH C:\\Qt\\Qt5.15.2\\5.15.2\\msvc2019_64) include_directories(include ) file(GLOB_RECURSE DIR_INC_PUB include/*.h) #Qt使用的时候 aux_source_directory(src DIR_SRC) find_package(Qt5 COMPONENTS Core REQUIRED) add_executable(MyClass ${DIR_SRC} ${DIR_INC_PUB} ) target_link_libraries(MyClass Qt5::Core )
这种结构中规中矩,会把Private类暴露给客户
第二种结构:Private对客户隐藏,不对外暴露在include文件夹里
这种时候不修改Cmake编译不通过
一种解决方案是去掉Private类里的Q_OBJECT宏,这时可以编译通过
另一种是修改CMake
file(GLOB_RECURSE DIR_INC_PRIVATE src/*.h) add_executable(MyClass ${DIR_SRC} ${DIR_INC_PUB} ${DIR_INC_PRIVATE})
原因是Private类的Q_OBJECT在编译期间moc展开未被正确连接。
当然,也可以把Private类的实现单独写在***Private.cpp,这个时候就不会有编译问题。
但这样的结构上就稍微不如之前的形式了。