qml查看器(适用于4.8和5.0)实现如下:
在.h(读者)我们有:
class QtQuick2ApplicationViewer : public QQuickView
{
Q_OBJECT
...
private:
class QtQuick2ApplicationViewerPrivate *d;
};
然后在.CPP文件中:
class QtQuick2ApplicationViewerPrivate
{
QString mainQmlFile;
friend class QtQuick2ApplicationViewer;
static QString adjustPath(const QString &path);
};
QtQuick2ApplicationViewer::QtQuick2ApplicationViewer(QWindow *parent)
: QQuickView(parent)
, d(new QtQuick2ApplicationViewerPrivate())
{
connect(engine(), SIGNAL(quit()), SLOT(close()));
setResizeMode(QQuickView::SizeRootObjectToView);
#ifdef Q_OS_ANDROID
engine()->setBaseUrl(QUrl::fromLocalFile("/"));
#endif
}
为什么在这里使用friend
?我没有看到任何人使用friend
课程的原因。有没有真正用于朋友课程(除了任何人都可以没有的异国情调)?
·H #include
class QtQuick2ApplicationViewer : public QQuickView
{
Q_OBJECT
public:
explicit QtQuick2ApplicationViewer(QWindow *parent = 0);
virtual ~QtQuick2ApplicationViewer();
void setMainQmlFile(const QString &file);
void addImportPath(const QString &path);
void showExpanded();
private:
class QtQuick2ApplicationViewerPrivate *d;
};
的.cpp
#include "qtquick2applicationviewer.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtQml/QQmlEngine>
class QtQuick2ApplicationViewerPrivate
{
QString mainQmlFile;
friend class QtQuick2ApplicationViewer;
static QString adjustPath(const QString &path);
};
QString QtQuick2ApplicationViewerPrivate::adjustPath(const QString &path)
{
#ifdef Q_OS_UNIX
#ifdef Q_OS_MAC
if (!QDir::isAbsolutePath(path))
return QString::fromLatin1("%1/../Resources/%2")
.arg(QCoreApplication::applicationDirPath(), path);
#elif !defined(Q_OS_ANDROID)
const QString pathInInstallDir =
QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), path);
if (QFileInfo(pathInInstallDir).exists())
return pathInInstallDir;
#endif
#endif
return path;
}
QtQuick2ApplicationViewer::QtQuick2ApplicationViewer(QWindow *parent)
: QQuickView(parent)
, d(new QtQuick2ApplicationViewerPrivate())
{
connect(engine(), SIGNAL(quit()), SLOT(close()));
setResizeMode(QQuickView::SizeRootObjectToView);
#ifdef Q_OS_ANDROID
engine()->setBaseUrl(QUrl::fromLocalFile("/"));
#endif
}
QtQuick2ApplicationViewer::~QtQuick2ApplicationViewer()
{
delete d;
}
void QtQuick2ApplicationViewer::setMainQmlFile(const QString &file)
{
d->mainQmlFile = QtQuick2ApplicationViewerPrivate::adjustPath(file);
setSource(QUrl::fromLocalFile(d->mainQmlFile));
}
void QtQuick2ApplicationViewer::addImportPath(const QString &path)
{
engine()->addImportPath(QtQuick2ApplicationViewerPrivate::adjustPath(path));
}
void QtQuick2ApplicationViewer::showExpanded()
{
#if defined(Q_WS_SIMULATOR)
showFullScreen();
#else
show();
#endif
}
答案 0 :(得分:6)
朋友检查朋友的私处。你肯定可以没有访问限制,但一旦你使用它,友好有助于亲密的情况。
答案 1 :(得分:2)
class Me;
class You {
friend class Me;
private:
Home _home;
Car _car;
public:
void bar(Me my);
};
class Me {
Stuff _stuff;
public:
foo(You you) {
//If you consider me a friend
you._home.enter(); //I can enter your `private _home`
you._car.drive(); //I can drive your `private _car`.
}
};
void You::bar(Me my) {
my.stuff //this is an error because I don't consider you a friend so you can't touch my `private _stuff`.
}
答案 2 :(得分:1)
知道你总是可以依靠我。这就是朋友的作用。 http://www.youtube.com/watch?v=xGbnua2kSa8
但我想你是在问C ++中的朋友课。
“范围”的重点是确切地定义谁可以看到另一个类中的内容。除了你需要“受保护”或“私人”之外你不需要“朋友”,因为你可以将所有课程中的所有内容公开,并且你的程序将成功编译和运行。但是这个想法是建立 - 并且记录 - 究竟什么是类的公共接口,因此如果不考虑对其他类的影响就不能改变,什么是内部实现,可以自由地重新编写或者重新组织,不用担心影响其他课程。
所以“朋友”的意思是说:嘿,我有这个类X,还有其他类Y.而且一般来说其他类不需要知道X如何去做它的工作。但Y与X中的某些低级事物交互,所以它需要看到它。因此,我让Y成为X的朋友。就像,我有一个投资者类,其功能(可能在其他方面)具有计算客户投资总额的功能。一般来说,其他课程不应该关心我如何进行计算:他们只想要总数。但现在我有一个TaxReporting课程,需要知道应税证券中有多少余额,以及非应税证券中有多少。也许我不想公开这些功能,因为这些信息是保密的,我想限制真实世界隐私的访问。更常见的是,我不想公开它,因为计算很棘手或经常变化,我想要严格控制哪些类访问它以限制事情发生变化时引起的问题。所以我让TaxReporting成为朋友,这样它就可以访问一些能够区分的函数,而无需向世界开放。
在实践中,当我做C ++时,我很少使用朋友。但“很少”不是“从不”。如果你发现自己说:“哦,我必须公开这个,这样其他一个班级才能看到它”,那么也许不应该公开你应该交朋友。
答案 3 :(得分:0)
“朋友”非常实用,是您想要一直使用的东西。
典型用例是:
您有一个使用子类的类,其中允许子类使用拥有子类的类的私有函数:
class ManagedObject
{
public:
void doStuff() { mMgr->updateManager(); }
private:
Manager* mMgr;
};
class Manager
{
friend ManagedObject;
public:
ManagedObject* createManagedObject();
private:
void updateManager() { }
};
所以在这种情况下,你有一个创建和处理“managedObject”的类。每当操作此对象时,它都需要更新创建它的对象。您希望类的用户知道他们不需要调用“updateManager”,实际上如果他们这样做就会生成编译时错误。
另一个常见的情况是,当你有一个类似于类成员的函数但由于某种原因不能成为类成员。一个例子是运算符&lt;&lt;。如果您编写自己的io流类,或者如果要创建用户操作符&lt;&lt;:
的序列化系统class serializedObject
{
public:
friend Serializer& operator<< ( Serializer& s, const serializedObject& obj );
protected:
u32 mSecretMember;
};
Serializer& operator<<( Serializer& s, serializedObject& obj )
{
serializer << obj.mSecretMember;
return s;
}
在这种情况下,序列化函数不能是serializedObject的成员,但需要查看serializedObject的内部序列来序列化它。您将看到类似的模式,您创建其他运算符(如加法),其中运算符的RHS与LHS不是同一类
答案 4 :(得分:0)
在Qt中,有一种称为“二进制兼容性保证”的东西,这意味着您的应用程序可以针对Qt4.8,4.8.1和4.8.2等运行而无需重新编译。
为了实现这一目标,对象的vtable无法改变。因此,Qt类是使用“PIMPL”(指向实现的指针)成语编写的。
“Private”类是公共类的PRIVATE实现 - 它是QtQuick2ApplicationViewer的实现细节。除了公共课外,全世界没有人知道私人班级。这两个类与设计密切相关。实际上,为了实现二进制兼容性保证,它们实际上是单个对象的不同方面,这些对象已经被c ++划分。
在这种情况下,私有类可以访问公共类是合理的。
答案 5 :(得分:-1)
2)在此背景下,quit
不是QApplication::quit()
,而是原因slot
,而是engine()
的一些内部信号。