3

いくつかの SO 記事を検索しましたが、私の質問に完全に対応するものは (まだ) 見つかりませんでした。この回答がすでにどこかに存在する場合はお詫び申し上げます。

最初に少し背景を...

機能が階層的なツリーのような構造を持つ、機能の「セクション」を持つデバイスを表現したいと考えています。のようなフラット化された関数をロードするのではなく、

DeviceReferenceCheck(), 
DeviceRefereceSet(), 
DevicePhaseSetX(), 
DevicePhaseDefaultsSet...()

代わりに、ネストされたクラスを活用して、取得できるようにしたいと思います

dev.reference.check()
dev.reference.set()
dev.phase.setx()
dev.phase.defaults.set...()

これを行うために、ネストされたクラスを使用して構造を取得しようとしていますobj.func.subfunction.subsub....()。ネストされたクラスは、そこで提供される読み取り/書き込み関数を使用する必要があるため、最も外側のクラスへの参照が必要です。

私の試みで、私がよく理解していない最初のことは次のとおりです...私はこれを自分で試しましたが、コンパイラの警告のために使用を中止しました。

class GPIBDevice_Agilent53132A : public GPIBDevice
{
private:
    class RefOsc {
    public:
        // ... snip ...
        RefOsc(GPIBDevice_Agilent53132A &parent);
        // ... snip ...
    } ro;
public:
   // ... snip ...
   GPIBDevice_Agilent53132A();
   // ... snip ...
};

GPIBDevice_Agilent53132A::GPIBDevice_Agilent53132A() : GPIBDevice(), ro(*this)
{
}

コンパイラは言う: gpibdevice_agilent53132a.cpp(5): warning C4355: 'this' : used in base member initializer list.

Aha, I think to myself... clever compiler... using this in the initialiser list is probably not a good idea because the class hasn't been fully constructed yet.

Question 1: Is what I've said above correct? Is using this, in the enclosing class' initialiser list, to give the nested class a reference to the enclosing class, a bad idea? My thoughts are "yes" but would like some clarification because in other SO threads I have seen this method being used (Nested Class member function can't access function of enclosing class. Why?).

My approach to get around this was to have a member pointer to nested and then when actually in the constructor (so now safe to use this as class has been constructed) made a new inner class where I could pass in the reference to *this without warnings. Is this the standard way of doing it?

Continuing on....

The reason for the private nested class is btw that I don't want the user to be able to instantiate that class him/herself. Now, I did have it public to begin with... tried to use a private constructor in the nested class, but then the compiler told me it couldn't construct the class. So presumably the enclosing class can see nested class private data members?

Question 2: Why can't the enclosing class see the nested classes private data members/functions?

My work around for this is to have the nested class declare the enclosing class as a friend. Is this really necessary?

Thanks for you help guys!

4

1 に答える 1

2

概要

奇妙に繰り返されるテンプレート パターンについて説明してくれたJanに感謝します。知っておくと面白い方法です。

質問に直接答えていると感じたので、私は自分の答えを受け入れることになりました。CRTP メソッドは優れていますが、質問 1 と 2 に直接答えることはできませんが、優れた代替手段を提供します。

質問1:

これは可能であるように思われます。mkirciR. Martinho Fernandesに感謝します。コンパイラが警告を生成した理由と、それを無視しても「安全」かどうかについての私の疑念を確認してくれました。

this要約すると...クラスがまだ構築されていないため、コンストラクターの初期化リストで使用するのは最善のアイデアではありません。みんなが指摘しているように、ポインターが使用されている場合、これにより UB が発生する可能性があります。内部クラスへのポインターを使用するという回避策を使用し、外部クラスのコンストラクター内で一度作成することにしました...このようにして、外部クラスは既に作成されており、それ自体への参照を内部クラスに渡すことができます安全にクラス。

質問2:

C++ 標準から、セクション 11.7 で (多くの掘り下げた後に) 見つけました。

ネストされたクラスはメンバーであるため、他のメンバーと同じアクセス権を持ちます。外側のクラスのメンバーには、ネストされたクラスのメンバーへの特別なアクセス権はありません。通常のアクセス規則 (第 11 条) に従うものとします。

標準では、次の例が示されています。

class E {
    int x;
    class B { };
    class I {
        B b; // OK: E::I can access E::B
        int y;
        void f(E* p, int i) {
            p->x = i; // OK: E::I can access E::x
        }
    };

    int g(I* p) {
        return p->y; // error: I::y is private
    }
};

したがって、これが (厄介なことに) 外部クラスが内部クラスのプライベート コンストラクターを呼び出せない理由です。私の解決策は、外側のクラスを内側のクラスの友達にすることでした。friend E;つまり、上記の例では、内部クラスの decl に追加します。

于 2013-07-15T12:52:02.453 に答える