C++学習5:ポインタ付きクラスの詳細(侯捷Stringクラスを例に)
12548 ワード
ポインタを持たないクラスと同様に、防衛式声明、前置声明が必要です.次に、クラスの定義、関数(メンバー関数とグローバル関数)の宣言と定義を行います.この部分の基本フレームワークは、ポインタを持たないクラスと同じです.参考:C++学習4:ポインタを持たないクラス(侯捷Complexクラスを例に)について詳しく説明します.次に、違いについて分析します.
1コード部
1.1 main関数
ポインタを持たないクラスとの主な違いを明確にするには、main関数を直接見てください.
ここでは、コピー構造、コピー付与の2つの主要な操作があります.その仕事はとても简単です:1つのbit 1つのbitのコピーと付与を行って、Complexクラスの中で定义がなくて、この时コンパイラはそれにセットをあげて、だからもあります.デフォルトのコピーポインタセットは、単純に1つの位置を指しているだけで、本当の構造ではないので、問題が発生します.だからデフォルトのバージョンは必ずしも十分ではありません.効果は私たちが望んでいるものではありません.
したがって、クラスにポインタがある限り、コピー構造とコピー付与操作を自分で書かなければなりません.
1.2クラスの定義
設計案:文字列のサイズが不明なため、文字列にポインタを持たせ、メモリが必要なときに作成します.この動的な割り当ての方法はもっとよくて、これとポインタをprivateの中に置いてください.get_c_str()関数:charタイプのポインタを返し、このクラスのデータを変更しません.だからconstをつけた(詳しくは一番上のリンクを参照).Big Three:1、コピーコンストラクタ:まずコンストラクタで、自分のタイプ名を関数として戻り値はありません.しかし、彼は自分のタイプと同じものを受け入れています.この例のようにパラメータもStringタイプで、これがコピーコンストラクタです.2、コピーコンストラクタ:賦値オペレータをリロードすることで、賦値の操作であることがわかります.彼が受けているのも自分と同じタイプのものです.この例では、パラメータもStringタイプであり、コピー割り当てです.3、構造関数:このクラスのオブジェクトが死亡した場合(役割ドメインを離れる場合など)、呼び出されます.
1.3関数の定義
以上がすべての定義です.構造関数があれば構造関数があることに注意してください.プロファイル処理は次の例で行われます(ここでは、新しい作成方法もあります).
s 2は括弧を離れると自動的に構造関数~String()が呼び出されるが,ここではdeleteがpを落とす必要がある.具体的なdeleteの原因は本稿の第3部を参照してください.
2クラスのポインタにはcopy_が必要ですctorとcopy_op=の原因
2.1コピー構造
以下の2つの文は、aというポインタが「hello」を指し、bというポインタが「world」を指すことを示す.デフォルトバージョンのコピーで値を割り当て、aが指す値をbに割り当てると、bit対bitの値に基づいて、bのポインタがaのポインタが指す位置を指す.
この場合を「浅いコピー」と呼ぶことによる結果:1、「world」という位置のメモリ漏れ2、aとbは同じ位置を指し、ポインタaの操作に直接このメモリに影響し、bも影響を受ける.aが「HELLO」に変更されると、bも「HELLO」になり、「別名」現象が現れる.3、2つのポインタは1つのメモリを指し、freeが1つ落ちたら、もう1つが野ポインタになるのは危険です.
深いコピー:真のコピーを実現するには、前に定義したコピー構造とコピー付与です.
コピー構造:s 1を手本とし、s 1と同じs 2を構築し、異なるメモリ領域に配置します.
2.2コピー付与
割り当てられるメモリを空にし、割り当てられる内容と同じ大きさの空間を割り当て、最後に格納すべきものを格納します.1、自己賦課値を検出する(功力が深い);2、deleteから自分を落とす.3、空間を開く.4、最後にコピーする.
1コード部
1.1 main関数
ポインタを持たないクラスとの主な違いを明確にするには、main関数を直接見てください.
int main()
{
String s1();
String s2("hello");
String s3(s1); // , :
cout << s3 << endl;
s3 = s2; // , :
cout << s3 << endl;
}
ここでは、コピー構造、コピー付与の2つの主要な操作があります.その仕事はとても简単です:1つのbit 1つのbitのコピーと付与を行って、Complexクラスの中で定义がなくて、この时コンパイラはそれにセットをあげて、だからもあります.デフォルトのコピーポインタセットは、単純に1つの位置を指しているだけで、本当の構造ではないので、問題が発生します.だからデフォルトのバージョンは必ずしも十分ではありません.効果は私たちが望んでいるものではありません.
したがって、クラスにポインタがある限り、コピー構造とコピー付与操作を自分で書かなければなりません.
1.2クラスの定義
class String
{
public:
String(const char* cstr = 0); //
String(const String& str); // -> 1
String& operator= (const String& str); // -> 2
~String(); // -> 3
char* get_c_str() const { return m_data; }
private:
char* m_data;
};
設計案:文字列のサイズが不明なため、文字列にポインタを持たせ、メモリが必要なときに作成します.この動的な割り当ての方法はもっとよくて、これとポインタをprivateの中に置いてください.get_c_str()関数:charタイプのポインタを返し、このクラスのデータを変更しません.だからconstをつけた(詳しくは一番上のリンクを参照).Big Three:1、コピーコンストラクタ:まずコンストラクタで、自分のタイプ名を関数として戻り値はありません.しかし、彼は自分のタイプと同じものを受け入れています.この例のようにパラメータもStringタイプで、これがコピーコンストラクタです.2、コピーコンストラクタ:賦値オペレータをリロードすることで、賦値の操作であることがわかります.彼が受けているのも自分と同じタイプのものです.この例では、パラメータもStringタイプであり、コピー割り当てです.3、構造関数:このクラスのオブジェクトが死亡した場合(役割ドメインを離れる場合など)、呼び出されます.
1.3関数の定義
inline
String::String(const char* cstr = 0)// , 0, 0
{
if (cstr)
{
m_data = new char[strlen(cstr) + 1];
strcpy(m_data, cstr);
}
else
{
m_data = new char[1];
*m_data = '\0';
}
}
inline
String::~String()//
{
delete[] m_data;
}
inline
String& String::operator=(const String& str)// , this
{
if (this == &str)//& , (& )
return *this;
delete[] m_data;
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
return *this;
}
ostream& operator<<(ostream& os, const String& str)
{
os << str.get_c_str();
return os;
}
以上がすべての定義です.構造関数があれば構造関数があることに注意してください.プロファイル処理は次の例で行われます(ここでは、新しい作成方法もあります).
{
String s2("hello");
String *p = new String("world");
delete p;
}
s 2は括弧を離れると自動的に構造関数~String()が呼び出されるが,ここではdeleteがpを落とす必要がある.具体的なdeleteの原因は本稿の第3部を参照してください.
2クラスのポインタにはcopy_が必要ですctorとcopy_op=の原因
String s2(s1);//s2 , ,
String s2 = s1;//s2 , s1 s2,
2.1コピー構造
以下の2つの文は、aというポインタが「hello」を指し、bというポインタが「world」を指すことを示す.デフォルトバージョンのコピーで値を割り当て、aが指す値をbに割り当てると、bit対bitの値に基づいて、bのポインタがaのポインタが指す位置を指す.
String a("hello");
String b("world");
この場合を「浅いコピー」と呼ぶことによる結果:1、「world」という位置のメモリ漏れ2、aとbは同じ位置を指し、ポインタaの操作に直接このメモリに影響し、bも影響を受ける.aが「HELLO」に変更されると、bも「HELLO」になり、「別名」現象が現れる.3、2つのポインタは1つのメモリを指し、freeが1つ落ちたら、もう1つが野ポインタになるのは危険です.
深いコピー:真のコピーを実現するには、前に定義したコピー構造とコピー付与です.
コピー構造:s 1を手本とし、s 1と同じs 2を構築し、異なるメモリ領域に配置します.
2.2コピー付与
割り当てられるメモリを空にし、割り当てられる内容と同じ大きさの空間を割り当て、最後に格納すべきものを格納します.1、自己賦課値を検出する(功力が深い);2、deleteから自分を落とす.3、空間を開く.4、最後にコピーする.