2

qml 查看器(适用于 4.8 和 5.0)是这样实现的:

在 .h(eader) 我们有:

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 #包括

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
}
4

6 回答 6

6

朋友检查朋友的私处。您当然可以完全不受访问限制,但是一旦您使用它,在亲密的情况下保持友好会有所帮助。

于 2012-10-25T14:58:50.503 回答
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`.
}
于 2012-10-25T15:28:57.373 回答
1

知道你总是可以依靠我,当然。这就是朋友的作用。http://www.youtube.com/watch?v=xGbnua2kSa8

但我猜你是在询问 C++ 中的朋友类。

“范围”的全部意义在于准确定义谁可以在另一个类中看到什么。您不再需要“朋友”,就像您需要“受保护”或“私人”一样,您可以将所有类中的所有内容公开,并且您的程序将成功编译和运行。但是这个想法是要建立——并记录——一个类的公共接口到底是什么,因此如果不考虑对其他类的影响就不能改变,什么是内部实现,可以自由地重新工作或重新组织,而不必担心影响其他班级。

所以“朋友”的意思是说:嘿,我有这个班级 X,还有另一个班级 Y。一般来说,其他班级不需要知道 X 是如何完成它的工作的。但是 Y 与 X 中的一些低级事物交互,所以它需要看到它。因此,我让 Y 成为 X 的朋友。就像,我有一个 Investor 类,它有一个函数(可能除其他外)有一个函数来计算客户的投资总额。一般来说,其他班级不应该关心我如何计算:他们只想要总数。但是现在我有一个 TaxReporting 类,它需要知道有多少余额是在应税证券中,有多少是在非应税证券中。也许我不想公开这些功能,因为这些信息是机密的,并且出于现实世界的隐私原因,我想限制访问。更多时候,我不想公开它,因为计算很棘手或经常更改,我想严格控制访问它的类以限制当事情发生变化时引起的问题。所以我让 TaxReporting 成为朋友,这样它就可以访问一些与众不同的功能,而无需向世界开放这些功能。

实际上,当我在做 C++ 时,我很少使用朋友。但“很少”不是“从不”。如果你发现自己说,“哦,我必须公开它,这样其他班级才能看到它”,那么也许你应该交一个朋友而不是公开它。

于 2012-10-25T15:14:24.537 回答
0

“朋友”非常有用,是您一直想使用的东西。

典型的用例是:

您有一个使用子类的类,其中允许子类使用拥有子类的类的私有函数:

class ManagedObject
{
public:
   void doStuff() { mMgr->updateManager(); }

private:
   Manager* mMgr;
};

class Manager
{
   friend ManagedObject;
public:
   ManagedObject* createManagedObject();

private:
   void updateManager() { }
};

因此,在这种情况下,您有一个创建和处理“managedObject”的类。每当操作此对象时,它都需要更新创建它的对象。您希望您的类的用户知道他们不需要调用“updateManager”,事实上,如果他们这样做,就会生成编译时错误。

另一个常见的情况是当你有一个函数,它像一个类成员,但由于某种原因不能成为一个类成员。一个例子是运算符<<。如果您编写自己的 io 流类,或者如果您想创建用户 operator<< 的序列化系统:

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 的类不同

于 2012-10-25T15:14:35.830 回答
0

在 Qt 中,有一种称为“二进制兼容性保证”的东西,这意味着您的应用程序可以在 Qt4.8、4.8.1 和 4.8.2 等环境下运行而无需重新编译。

为了实现这一点,对象的 vtable 不能更改。因此,Qt 类是使用“PIMPL”(指向实现的指针)习语编写的。

“Private”类是公共类的 PRIVATE 实现——它是 QtQuick2ApplicationViewer 的实现细节。全世界除了公开课外,没有人知道私人课。这两个类在设计上深深地交织在一起。事实上,它们实际上是单个对象的不同方面,为了实现二进制兼容性保证,已经按照 c++ 进行了分区。

在这种情况下,私有类可以访问公共类是合理的。

于 2014-02-05T00:33:44.137 回答
-1

2) 在这种情况下quit,不是QApplication::quit(),那是slot原因,而是 的一些内部信号engine()

于 2012-10-25T15:07:42.113 回答