C++11とか14とか難しいですよね。。
Effective modern c++を読んで自分なりに理解したことをメモして変なプログラムで実装してみたいと思います。。
盛大なツッコミを期待しています。
c++11にはstd::unique_ptr, std::shared_ptr, std::weak_ptrとおまけでstd::auto_ptrがあります。
歴史的に見たらauto_ptrはたしか03くらいからありますが、多分もうほとんど使われません。
Smartpointer
unique_ptrを所有できるのは宣言された本人のみでその参照がなくなると破壊されます。uniqueたんがmoveされると、所有権が移りもともとのsource pointerはnullに戻ります。uniqueにコピーは許されていません。なぜならコピーされるとsourceとそのうつしたあとのさきのpointerは同じものを参照していることになりuniqueのowenershipは一つという規約に反するからです。shared_ptrはsorce pointerを複数のownerがシェアできます。シェアエコノミーyeah!
よって、unique_ptrはmoveのみです!
Factory function
ここでイーブイクラスをベースにchild classにシャワーズ(Vaporean)があるようなクラスを考えます。
なんか、unique_ptrの典型的な使用例はHierarchyなobjectを作る関数だからみたいです。この関数(meetEevee)はheapにobjectを作りpointerをかえします。条件分けをし、必要なtypeのobjectを返すような関数です。
defaultでは何もログを残さず消えていくuniqueをlambda expressionを用いてログを残して消えるようにしましょうc++14ではautoとtype宣言するだけでいいです。
Eeveeのクラスのdestructorはvirtual でなければなりません。custom deleterはtype Eevee*をとります。inheritedなVaporeonが破壊される時もベースとなるEeveeのdestructorを通じて破壊されるからです。
#include <iostream>
#include <iomanip>
using namespace std;
class Eevee{
protected:
int level;
int attack;
int defence;
bool evol;
std::shared_ptr<string> stoneType;
public:
explicit Eevee() : level(25), attack(55), defence(50), evol(false){
stoneType.reset(new string("none"));
};
explicit Eevee(int l, int a, int d) : level(l), attack(a), defence(d), evol(false){
stoneType.reset(new string("none"));
};
virtual ~Eevee(){
std::cout << "Your eevee died at level: " << level << std::endl;
}
virtual void setStone(string stone) {
if(!evol) {
stoneType.reset(new string(stone));
bool evol = true;
}
}
void showStatus() {
std::cout << setw(3)<< level<< setw(3)<< attack << setw(3)<< defence << setw(3) << endl;
}
};
class Vaporeon: public Eevee{
public:
explicit Vaporeon() {
std::cout << "constructor called" << std::endl;
stoneType.reset(new string("water"));
evol = true;
};
explicit Vaporeon(int l, int a, int d){
level = l, attack = a, defence = d;
std::cout << "arg constructor called" << std::endl;
stoneType.reset(new string("water"));
evol = true;
std::cout << setw(3)<< level<< setw(3)<< attack << setw(3)<< defence << setw(3) << endl;
};
virtual ~Vaporeon() override {
std::cout << "Your vaporeon died at level: " << level << std::endl;
}
};
template<typename Ts>
auto meetEevee(Ts&& l, Ts&& a, Ts&& d, int type)
{
auto delEevee = [](Eevee* pEevee)
{
std::cout << "delEevee called" << std::endl;
pEevee->showStatus();
delete pEevee;
};
std::unique_ptr<Eevee, decltype(delEevee)> pEevee(nullptr, delEevee);
if(type == 1) {
pEevee.reset(new Vaporeon(std::forward<Ts>(l), std::forward<Ts>(a), std::forward<Ts>(d)));
}else {
std::cerr << "unknown type" << std::endl;
}
return pEevee;
}
int main(void)
{
//Vaporeon(31, 89, 29);
meetEevee(55, 80, 49, 1);
//meetEevee()
return 0;
}