operator() 進階用法 繼承
如果你有兩個以上的陣列類別,你就必須為他們個別重載所有的 operator 運算子,又他們很有可能都是完全一樣的,你只是想對那個陣列做運算不會動到其他成員,他們的差別只在於型態不一樣,彼此互相有不同的資料成員。
最好的解法就是把他們的陣列拉出來用template實作,並為他們重載需要的 operator 然後再用正確的型態繼承到個別的類別。
比如說父類別為
Arr<T>
子類別為
Arr_int
Arr_double
Arr_char
我們總不可能為了這三個個別寫了各自完全一樣,只有型態不行的運算子重載,一個
+
就需要用 +=
與 +
,如果還做了常數的相加Arr_int a;
a=a+1;
a=1+a;
又需要多寫2個重載函式,相當於一個運算符號需要4個函式,總共有4個符號所以是16個,我們做了3個類別需要寫了16*3個。
繼承後會遇到一些問題,這裡附上可能發生的問題與他的解法
資料結構
這是我們的主類別
template <typename T>
class Arr {
Arr(initializer_list<T> i): arr(i){}
Arr & operator+=(Arr const& rhs);
protected:
vector<T> arr;
};
Arr<T1> operator+(Arr<T1> const &lhs, Arr<T1> const &rhs){...}
這是繼承後的子類別
class Arr_int: public Arr<int>{
public:
Arr_int(initializer_list<int> i): Arr<int>(i), i(-1){}
public:
int i;
};
上下轉型的問題
加號產生的暫存父類別
這個問題發生在某些情況,或某些情況必然會遇到分別是
Arr_int a{0}, b{0};
a = b+b;
這裡因為我們的 + 函式的定義返還值為
Arr<int>
與 Arr_int
不符合會導致Arr_int = Arr<int>
讓他等於父類別
Arr<int> f{0};
Arr_int a{0};
a = f;
原因與解法
父類別型態出現在等號右邊,可是函式內預設只會建立
arr_int & arr_int::operator=(arr_int const & rhs);
他會找不到函式呀,我們需要多載正確的型態等號
Arr_int & operator=(Arr<int> const & rhs);
至於裡面的實作我們可以呼叫父類別來做
Arr_int & operator=(Arr<int> const & rhs){
this->Arr<int>::operator=(rhs);
// other ...
return (*this);
}
這會導致子類別的多出來的成員不會被操作到,如果需要用上則在這裡補上。加號也是一樣如果需要的話則用這種方式減少代碼的重複。
繼承後如何轉名
這種做法會導致所有的子類別名稱都是
vector<T> arr;
我們可以透過參考的方式對他重新命名,取一個別名
public:
// 更換別名
decltype(arr) & mask = arr;
如此一來就可以自由地操作了。
實作範例
inhereit.hpp
/*****************************************************************
Name :
Date : 2017/03/17
By : CharlotteHonG
Final: 2017/03/17
*****************************************************************/
#include <iostream>
#include <vector>
#include <initializer_list>
using namespace std;
template <typename T>
class Arr {
public:
Arr(initializer_list<T> i): arr(i){}
Arr & operator=(Arr<T> const & rhs) = default;
public:
void pri(string name=""){
cout << name << " = ";
for(auto&& i : arr) {
cout << i << ", ";
}cout << endl;
}
public:
// 重載下標符號
T & operator[](size_t idx){
return const_cast<T&>(static_cast<const Arr&>(*this)[idx]);
}
const T & operator[](size_t idx) const{
return arr[idx];
}
// 重載+=符號
template <typename T1> friend
Arr<T1> operator+(Arr<T1> const &lhs, Arr<T1> const &rhs);
Arr & operator+=(Arr const& rhs){
for(unsigned i = 0; i < arr.size(); ++i)
(*this)[i] += rhs[i];
return (*this);
}
Arr & operator+=(T const &rhs){
for(unsigned i = 0; i < arr.size(); ++i)
(*this)[i] += rhs;
return (*this);
}
protected:
vector<T> arr;
};
// 重載+符號(全域函式)
template <typename T1>
Arr<T1> operator+(Arr<T1> const &lhs, Arr<T1> const &rhs){
return Arr<T1>(lhs) += rhs;
}
//----------------------------------------------------------------
class Arr_int: public Arr<int>{
public:
Arr_int(initializer_list<int> i): Arr<int>(i), i(-1){}
Arr_int(Arr<int> const & rhs):Arr<int>(rhs), i(-1){}
Arr_int & operator=(Arr<int> const & rhs){
this->Arr<int>::operator=(rhs);
return (*this);
}
public:
int i;
};
using uch = unsigned char;
class Arr_uch: public Arr<uch>{
public:
// 更換別名
decltype(arr) & mask = arr;
public:
Arr_uch(initializer_list<uch> i): Arr<uch>(i){}
Arr_uch(Arr<uch> const & rhs):Arr<uch>(rhs){}
Arr_uch & operator=(Arr<uch> const & rhs){
(*this).Arr<uch>::operator=(rhs);
return (*this);
}
};
//----------------------------------------------------------------
inhereit_main.cpp
/*****************************************************************
Name : 無損繼承 operator
Date : 2017/03/17
By : CharlotteHonG
Final: 2017/03/17
*****************************************************************/
#include <iostream>
#include "inhereit.hpp"
using namespace std;
/*==============================================================*/
int main(int argc, char const *argv[]){
Arr<int> a{0, 1, 2};
Arr<int> b{0, 1, 2};
b=b+a;
b.pri("b+a");
// 繼承運算符號
Arr_int c{1, 1, 1};
Arr_int c1{1, 1, 1};
c.i=7;
c1.i=8;
c = c1+c1;
cout << c.i << " || ";
c.pri("c1+c1");
// 繼承的 += 操作符號不會操作子類別成員
c += c1;
cout << c.i << " || ";
c.pri("c+=c1");
// 複製建構子
Arr_int c2(c1);
cout << c2.i << " || ";
c2.pri("c2");
Arr_int c3(c+c); // c+c 返還的是父類別
cout << c3.i << " || ";
c3.pri("c3");
// 繼承運算符號2
Arr_uch d{'0', '0', '0'};
Arr<unsigned char> ch{'0', '0', '0'};
d = d+d;
d.pri("d+d");
return 0;
}
/*==============================================================*/
沒有留言:
張貼留言