Last active
March 9, 2016 00:49
-
-
Save es-kumagai/908f93a41c5135147c27 to your computer and use it in GitHub Desktop.
たまにはちょっと C++ で。Swift プロトコル拡張の動きを見てたら C++ のクラスの動き「隠蔽」と「オーバーライド」の差異を思い出した。 #swift #CodePiece
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
class CBase { | |
public: | |
/// 非・仮想メソッドは、同名のものを派生クラスで実装すると隠蔽 (conceal かな?) されます。 | |
std::string method() { | |
return "Base"; | |
} | |
/// 仮想メソッドは、同名のものを派生クラスで実装するとオーバーライド (override) されます。 | |
virtual std::string virtualMethod() { | |
return "Base (virtual)"; | |
} | |
}; | |
class CSub : public CBase { | |
public: | |
/// 基底クラスにある同名のメソッドが非・仮想メソッドなので、それを隠蔽します。 | |
std::string method() { | |
return "Sub"; | |
} | |
/// 基底クラスにある同名のメソッドが仮想メソッドなので、それをオーバーライドします。 | |
/// override キーワードは「オーバーライドしたつもりがしてなかった」を検出するためだけに使います。 | |
std::string virtualMethod() override { | |
return "Sub (virtual)"; | |
} | |
}; | |
int main(int argc, const char * argv[]) { | |
/** | |
型として扱った場合、 | |
すべての場合 (method, virtualMethod) で、 | |
オーバーライドの関係を無視した動作を見せる。 | |
*/ | |
std::cout << "型そのものでクラスを扱うと、仮想メソッドとか抜きに、指定した型で振る舞います。" << std::endl; | |
std::cout << "動作的に見れば、なんとなく Swift のプロトコル拡張(メソッドの宣言なしの時)に似てるかもしれません。" << std::endl; | |
CBase baseInBase = CBase(); | |
CBase subInBase = CSub(); | |
CSub subInSub = CSub(); | |
std::cout << baseInBase.method() << std::endl; // "Base" | |
std::cout << baseInBase.virtualMethod() << std::endl; // "Base (virtual)" | |
std::cout << subInBase.method() << std::endl; // "Base" | |
std::cout << subInBase.virtualMethod() << std::endl; // "Base (virtual)" | |
std::cout << subInSub.method() << std::endl; // "Sub" | |
std::cout << subInSub.virtualMethod() << std::endl; // "Sub (virtual)" | |
/** | |
ポインターとして扱った場合、 | |
仮想メソッド (virtualMethod) は、オーバーライド関係を考慮する。 | |
非・仮想メソッド (method) は、オーバーライドの関係を無視する。 | |
*/ | |
std::cout << "ポインターでクラスを扱うと、仮想メソッドが生きてきます。" << std::endl; | |
std::cout << "動作的に見れば、こちらは Swift のオブジェクト指向そのものです。" << std::endl; | |
auto pBaseInBase = std::unique_ptr<CBase>(new CBase()); | |
auto pSubInBase = std::unique_ptr<CBase>(new CSub()); | |
auto pSubInSub = std::unique_ptr<CSub>(new CSub()); | |
std::cout << pBaseInBase->method() << std::endl; // "Base" | |
std::cout << pBaseInBase->virtualMethod() << std::endl; // "Base (virtual)" | |
std::cout << pSubInBase->method() << std::endl; // "Base" | |
std::cout << pSubInBase->virtualMethod() << std::endl; // "Sub (virtual)" | |
std::cout << pSubInSub->method() << std::endl; // "Sub" | |
std::cout << pSubInSub->virtualMethod() << std::endl; // "Sub (virtual)" | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment