Data Memberのバインド

5717 ワード

次のコードについて考察します.
extern float _x;



//user code

class Point3d

{

public:

    Point3d(float, float, float);

    // ,   _x?

    float X() const {return _x;}

    void  X(float x) const { _x = x;}

private:

    float _x, _y, _z;

};

多くの人がclassの中のはずだと言うかもしれません.xですが、異なるコンパイラで動作が一致することを保証するのは難しいため、以下の2つの防御的な設計スタイルがあります.
class Point3d

{

    //#1

    //  class   data member

    float x, y, z;

public:

    float X() const {return _x;}

    //...

};



class Point3d

{

    //#2

    //  inline   class  

    Point3d();

    float X() const;

    void X(float) const;

    //...

};



inline float

Point3d:: X() const {return _x;}

このスタイルは現在まで存在していますが、C++2.0の後、class宣言全体が表示されない前にinline関数エンティティが評価されないというルールがあります.つまり、次のコードを考察します.
extern int _x;



class Point3d

{

public:

    // 

    //  class  

    float X() const {return _x;}

private:

    float _x;

};

// ,   class  

したがって、inlineメンバーfunctionボディ内のdataメンバーバインド操作は、class宣言全体の後に発生します.しかし,これはmember functionのargumentリストにとって真ではない.Argumentリストの名前は、最初に遭遇したときに適切にresolveされます.したがってexternとnested type namesの間の非直感的なバインドが発生するかどうか、以下のコードを考察します.
typedef int length;



class Point3d

{

public:

    //wtf!length   resolve   global

    // , _val   resolve   Pointd::_val

    void mumble(length val) {_val = val;}    //    length  

    length mumble() {return _val;}

    //...

private:

    //length   class  

    // 

    typedef float length;

    length _val;

};

このような場合、nwsted type宣言をclassの先頭に置くと、非直感的なバインドを避けることができる前の防御スタイルが必要です.