const-correctness
がどのように機能し、より具体的には、メンバーがcontainers
とsmart pointers
に基づいているクラスを扱う場合、よりよく理解しようとしています。 const-correctness
プロパティは、クラスメンバーに関係なく同じであると思います。しかし、何が起こっているのかを明確に理解するのが難しいので、 私はアドバイスを求めることにしました。スマートポインタでの正確さの正確さ
だから、ここにその文脈があります。私はShapeContainer
クラスを持っていて、それはプライベートクラスのメンバとしてスマートポインタのベクトルを持っています。 Shape
クラスは抽象クラスであり、次の仮想関数virtual float doSomething();
を持ち、その派生クラスによって再定義されます。これは非constクラス関数であることに注意してください。 は、コードの該当部分を以下に示す:ここでは
class ShapeContainer{
public:
typedef std::shared_ptr<Shape> ShapePtr;
typedef std::vector<ShapePtr> ShapePtrContainer;
// .......
const ShapePtr & operator[](int) const { return m_vect[index]; }; // const version
// ShapePtr & operator[](int) { return m_vect[index]; }; // non-const version
// .......
private:
ShapePtrContainer m_vect;
};
class Shape{
public:
// ...
virtual float doSomething() = 0;
};
私の質問です。
Q1。なぜ、doSomething()
関数をint index = 0; float tmp = container1[index]->doSomething();
(ShapeContainer container1=createBasicShapes();
)と呼ぶことができますか?私が理解から
は、我々はShape
オブジェクトへconst
のポインタを取得しますconst ShapePtr operator[] const
機能を呼び出した後、しかしdoSomething()
仮想 機能はのconstではありません。ですから、constオブジェクトへの参照は非const関数をどのように呼び出すことができますか?
Q2。 operator[]
のnon-const
バージョンを追加することによってpreviouly ilustrated(float tmp =container1[index]->doSomething();
)ととしてdoSomething()
関数を呼び出すことによって、このlatter
オーバーロードされたバージョンは、代わりにconst-version
一つで呼ばれています。なぜそれはそうですか?
さて、代わりにShapeContainer
クラスを有するので、私は今まだvector
を持っていますが(クラスメンバーとしてのスマートポインタを持っている)中間ShapeInfo
クラスのShapeContainerInfo
という名前の新しいクラスをしました。
class ShapeContainerInfo{
public:
typedef std::vector<ShapeInfo> ShapeContainer;
const ShapeInfo & operator [](int index) const { return m_vect[index]; };
// ShapeInfo & operator [](int index) { return m_vect[index]; }; // non-const version
private:
ShapeContainer m_vect;
};
class ShapeInfo{
public:
typedef std::shared_ptr<Shape> ShapePtr;
// ...
float doSomething(){ return m_ShapePtr->doSomething(); };
private:
ShapePtr m_ShapePtr;
int m_nID;
};
Q3。 float tmp = container2[i].doSomething();
を呼び出すと、次のコンパイラエラーが発生します。error C2662: 'ShapeInfo::doSomething' : cannot convert 'this' pointer from 'const ShapeInfo' to 'ShapeInfo &'
しかし、私がnon-const
オーバーロードされたoperator []
のvesionを追加すると、コンパイラのエラーはなくなります。だから、なぜShapeContainerInfo
にはnon-const operator[]
が本当に必要で、ShapeContainer
には必要ないのですか?
4。 public
部材とoperator[]
のみ CONSTバージョンが(ないnon-const
1)で定義した通りであるShapeContainerInfo
のm_vect
private
メンバーは現在設定されている場合、コンパイラエラーメッセージが存在しません。なぜこれ?例えばm_vect
をパブリッククラスメンバに設定した後:float tmp = info.m_vect[i].doSomething();
Q5。 ShapeInfo
とShapeContainerInfo
クラスの両方を正しく定義すれば、operator[]
のconst-version
を定義するだけで、まだfloat doSomething()
関数を呼び出すことができます。
サンプルコード全体に興味のある方は、hereをご覧ください。
明確化、提案は常に歓迎されます:-) Merci!
。 'Q3'の答えに関して、私は' std :: vector'を 'non-const'と定義しました。あるいは、正確にどこの' vector'が 'const'と見なされるのでしょうか? Q4/Q5の提案はありますか? – Tin
@Tin:メンバ関数がconstなので、クラスのすべてのメンバはその関数内のconstとみなされます。私はまだQ5を分析しています。 –
@ Benjamin、実際はそうではありません。私がしたのは:float tmp = info.m_vect [i] .doSomething();この場合、私はm_vectをprivateクラスではなくpublicクラスメンバに設定しました。それに加えて、私は演算子[]の 'constバージョン 'だけを考えました。 – Tin