C++でのさまざまな演算子のオーバーロードについて詳しく説明する
1.等しい演算子のオーバーロード
注意が必要なのは、等号演算子をオーバーロードしない場合、システムはデフォルトで等号演算子のオーバーロードを浅い代入の形式で生成することです。いわゆる浅い代入は、メンバーのプロパティを直接割り当てることです。ターゲットオブジェクトの現在のオブジェクトへの変換(ディープコピーを参照)およびシャローコピー。詳細については、私の記事「C++-コピーコンストラクターの説明」で説明しています。
Object
{
public:
//其他的构造函数、析构函数不是本篇文章重点,省略。
void operator=(const Object& obj)
{
this->value=obj.value;
}
/*
在主函数中使用obja=objb=objc,等价于下面的方法调用:
obja=objb.operator=(objc);
obja=operator=(&objb,objc);
*/
private:
int value;
}
上記の代入文については、次の3点を説明する必要があります
。①この代入文は、代入の過程で値が変化するため、constで変更
できません②このメソッドは、戻り値が無効であるため、連続代入を実装できません。 voidをObjectに変更すると、連続代入が可能になります
。③オブジェクトはmain関数内にあるため、参照により現在のメソッドに入り、objオブジェクトはこのオーバーロードされた関数の呼び出し期間の影響を受けません。参照により返送できるように
等号演算子をオーバーロードする場合は、次の2つの場合があり
ます。①自分で設計した型とオブジェクトはなく、どちらも基本型である場合、システムは2つのオブジェクトのメンバー属性アドレスをキャプチャし、のデータを直接インポートします。ターゲットオブジェクトのメンバー属性を現在のオブジェクトメンバープロパティに追加します。
②メンバープロパティに基本タイプ以上のものがある場合、等号演算子をオーバーロードしないと、システムはデフォルトの浅い代入ステートメントを生成します。
2、および演算子のオーバーロード
class Int
{
private:
int value;
public:
//前置加加
Int& operator++()
{
this->value+=1;
return *this;
}
//后置加加
Int operator++(int)
{
Int tmp = *this;
++* this;//调用前置加加
return tmp;
}
//对象+对象
Int operator+(Int& b)const
{
Int c;
c.value = this->value + b.value;
return c;
}
//对象+数值
Int operator+(int val)const
{
Int c;
c.value = this->value + val;
return c;
}
};
//数值+对象
Int operator+(const int val, const Int& a)
{
return a + val;//调用Int operator+(int val)const 这个方法
}
3.アドレス演算子のオーバーロード
class Int
{
private:
int value;
public:
//省略构造函数、等号运算符重载,这里主要说明取地址运算符重载
Int* operator&()
{
return this;
}
const Int* operator&()const//加了const的取地址运算符重载是一个常方法
{
return this;
}
}
int main()
{
Int a(10);
Int b=10;//这句话会先调用构造函数构造一个value成员属性为10的对象,然后把这个对象赋值给b
const Int c=10;
const Int *ip=&c;//因为C是常对象,所以就会调用上面的常方法
}
4、++前、++後の演算子のオーバーロード
4.1ポスト++参照の問題:
次のコードからわかるように、ポスト++であるため、元の値を保存するオブジェクトを作成してから、現在の値を1ずつ追加する必要があります。ただし、作成されたオブジェクトの存続期間とオーバーライドの方法post ++メソッドlifetimeと同様に、関数呼び出しが終了すると、スペースが解放されます。したがって、参照を返すことはできません。
//后置加加
Int operator++(int)
{
Int tmp = *this;
++* this;//调用前置加加
return tmp;
}
しかし、参照を返す必要がある場合、静的を追加できますか?次のように:
Int& operator++(int)
{
static Int old=*this;
++* this;
return old;
}
上記のコードは静的として定義されているため、post ++を1回実行しても問題はありませんが、静的であるため、static Int old = * thisのみを実行します。一度、post ++を再度実行すると、値は、または前の値を変更しない場合は、次のように変更します。
Int& operator++(int)
{
static Int old=*this;
old=*this;
++* this;
return old;
}
old = * thisという文を追加した後、post-addメソッドを実行するたびに、静的変数oldが現在のオブジェクトに再割り当てされるため、前述の「post-add++が再度実行されたときに値は変わりません。以前と同じ値です。」
変更されたコードを説明する例:
old = * this;は古いものを更新するため、最後のd出力は12です。
4.2関連する問題の分析
次の演算子のオーバーロードと組み合わせて、Int a = 0; a = a+++1;のコードを分析します。
5、オーバーロード型キャスト演算子
(1)暗黙の型変換:
いわゆる暗黙の型変換は、次の例で説明されます。a
= b、この文は実際には最初に整数bの値で作成され、作成されたオブジェクトをaに割り当てます。呼び出しが終了し、このオブジェクトが破棄され、aが破棄されます。
(暗黙の変換を許可しないキーワード:明示的)
暗黙的な型変換が可能なコンストラクターは単一のパラメーターでなければならないことを強調しておく必要があります
(2)強制型変換:
オブジェクトは強制的に組み込み型になります
//把对象强转成整型
operator int() const
{
return value;
}
強制によって返される型は強制後の型であるため、オーバーロードされた関数は戻り型を設定する必要はありません
。たとえば、次のようになります。flotが返されると、戻り型と競合します。
6.括弧演算子のオーバーロード
class Add
{
mutable int value;//加了mutable这个关键字之后,可以让value这个变量在常方法中也能改变
public:
Add(int x=0):value(x){
};
int operator()(int a,int b)const//括号运算符重载
{
value=a+b;
return value;
}
}
int main()
{
int a=10,b=20,c=0;
Add add;
c=add(a,b);//调用括号运算符重载,我们也称之为仿函数
//c=add.operator()(a,b);
return 0;
}
7.出力演算子のオーバーロード
次の出力演算子のオーバーロードは間違っています。outパラメータは、参照によって呼び出す必要があります。システムコードはプライベート出力ストリームを設定するため、参照呼び出しである必要があります。参照呼び出しでない場合は、コピー構造が呼び出され、コピー構造はプライベートに設定されます。呼び出すことはできません。
class String
{
private:
char * str;
public:
//ostream& operator<<(const String* const this,ostream& out)
ostream& operator<<(ostream out)const
{
if(str!=NULL)
{
out<<str;
}
return out;
}
//s1<cout
//s1.operator<<(cout)
//operator(&s1,cout)
}
正しいものは次のとおりです
。strの内容をコロケーションに書き込んで返し
ます。ただし、上記の出力演算子のオーバーロードは次のとおりです。s1 << cout、論理出力演算子のオーバーロードに準拠していません。
したがって、
ostream&operatorを呼び出します。 <<(ostream&out、const String&s)
次に、オブジェクト内で出力演算子のオーバーロードを呼び出します
class String
{
private:
char * str;
public:
//ostream& operator<<(const String* const this,ostream& out)
ostream& operator<<(ostream& out)const
{
if(str!=NULL)
{
out<<str;
}
return out;
}
//s1<cout
//s1.operator<<(cout)
//operator(&s1,cout)
}
ostream& operator<<(ostream& out,const String& s)
{
s<<out;
//s.operator<<(out);
//operator<<(&s,out);
return out;
}
int main()
{
String s1("hello world");
cout<<s1<<endl<<;
return 0;
}
8.アスタリスク演算子のオーバーロード
class Int
{
private:
int value;
};
class Object
{
Int* ip;//Int是一个类
public:
Object(Int* s=NULL):ip(s){
}
~Object()
{
if(ip!=NULL)
{
delete ip;
}
ip=NULL;
}
//✳运算符重载返回这个对象所指向的地址
Int* operator*()
{
return ip;
}
const Int* operator*()const
{
return ip;
}
//✳运算符重载返回ip所指向的对象
Int& operator*()
{
return *ip;
}
const Int& operator*()const
{
return *ip;
}
};
int main()
{
Object obj(new Int(10));
(*obj)->value();
}
9.ポインター演算子のオーバーロード
class Int
{
private:
int value;
};
class Object
{
Int* ip;//Int是一个类
public:
Object(Int* s=NULL):ip(s){
}
~Object()
{
if(ip!=NULL)
{
delete ip;
}
ip=NULL;
}
//返回所指向的这个对象的地址
const Int* operator->()const
{
return ip;
}
}
int main()
{
Object obj(new Int(10));
obj->value();
}
注:「オブジェクトの自由な使用」の問題は、アスタリスク演算子のオーバーロードとポインティング演算子のオーバーロードを組み合わせて使用することで実現されます。問題は次のことをもたらします
。
class Int
{
private:
int value;
};
class Object
{
Int* ip;//Int是一个类
public:
Object(Int* s=NULL):ip(s){
}
~Object()
{
if(ip!=NULL)
{
delete ip;
}
ip=NULL;
}
Int& operator*()//重载*,返回ip所指对象本身
{
return *ip;
}
const Int& operator*()const
{
return *ip;
}
Int* operator->()
{
return &**this;
}
const Int* operator->()const
{
return &**this;
//return ip
}
}
上記の&**これはどういう意味ですか?
上記のコードでは、次の図と組み合わせて右から左に分析します。これはobjオブジェクトを参照し、*これはobjオブジェクトを示し、**これは✳演算子のオーバーロードを呼び出し、によって示されるオブジェクトを示します。 ip自体、つまりこのTogetherは、ipが指すオブジェクトのアドレスを表します。
したがって、✳演算子と->演算子を入力した後、Intオブジェクトも取得でき、Obj形式を使用して自由化を実現します。つまり、デストラクタでは、この時点で、ipが指すヒープのスペースは自動的に破棄されるため、手動で解放する必要はありません。