Skip to content

Instantly share code, notes, and snippets.

@es-kumagai
Last active March 9, 2016 00:49
Show Gist options
  • Save es-kumagai/908f93a41c5135147c27 to your computer and use it in GitHub Desktop.
Save es-kumagai/908f93a41c5135147c27 to your computer and use it in GitHub Desktop.
たまにはちょっと C++ で。Swift プロトコル拡張の動きを見てたら C++ のクラスの動き「隠蔽」と「オーバーライド」の差異を思い出した。 #swift #CodePiece
#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