c++マルチステート詳細例

5826 ワード

*C++マルチステートはコンパイル時マルチステートと実行時マルチステートに分けられます.*コンパイル時のマルチステートは、例1.*実行時のマルチステートは、例2.*キーワードvirtualはfunction declarationまたはclass declarationに使用できます.*キーワードvirtualが関数を修飾するときに虚関数を宣言します.*キーワードvirtualがクラスを修飾するときに虚ベースクラス(virtual base class)を宣言する.虚基類の役割は空間を節約し、重複と二義性を避け、多態とは関係ない.*抽象クラス(abstract class)=純粋な虚関数(pure virtual function)を含むクラス(自分で宣言しても継承しても)、例6.1.一般メンバー関数への呼び出しはポインタ/参照のタイプによって決まる(コンパイル時マルチステート)
#include <iostream>
using namespace std;

class B
{
public: void vf() { cout << "This is class B" << endl; }
};

class D: public B
{
public: void vf() { cout << "This is class D" << endl; }
};

main()
{
B b, *pb;
D d, *pd;
pb = &b; pb->vf();
pb = &d; pb->vf(); // no cast needed
pd = (D*)&b; pd->vf(); // must cast explicitly
pd = &d; pd->vf();
}
This is class B
This is class B
This is class D
This is class D
2.虚関数の呼び出しはポインタ/参照の付与により決定する(実行時マルチステート)
#include <iostream>
using namespace std;

class B
{
public: void virtual vf() { cout << "This is class B" << endl; }
};

class D: public B
{
public: void vf() { cout << "This is class D" << endl; }
};

main()
{
B b, *pb;
D d, *pd;
pb = &b; pb->vf();
pb = &d; pb->vf();
pd = (D*)&b; pd->vf();
pd = &d; pd->vf();
}
This is class B
This is class D
This is class B
This is class D
3.一般メンバー関数は呼び出されなければ関数の内容を定義しなくてもよい
#include <iostream>
using namespace std;

class B
{
// non-virtual function may be undefined as long as it's not called
public: void vf();
};

class D: public B
{
public: void vf() { cout << "This is class D" << endl; }
};

main()
{
B b, *pb;
D d, *pd;
pd = (D*)&b; pd->vf();
pd = &d; pd->vf();
}
This is class D
This is class D
4.ベースクラス虚関数は、内容または純虚関数を定義する必要がある(そうでなければ、そのベースクラスとその派生クラスはすべてインスタンス化できない)
#include <iostream>
using namespace std;

class B
{
// virtual function in base class must be defined or be pure
// unless the base class and all its derived classes are not instantiated
public: void virtual vf();
};

class D: public B
{
public: void vf() { cout << "This is class D" << endl; }
};

main()
{
D d, *pd;
}
error LNK2001:
unresolved external symbol "public: virtual void __thiscall B::vf(void)" (?vf@B@@UAEXXZ)
5.派生クラス虚関数この派生クラスがインスタンス化されていなければ(もちろん何の役にも立たない)内容を定義しなくてもよい
#include <iostream>
using namespace std;

class B
{
public: void virtual vf() { cout << "This is class B" << endl; }
};

class D: public B
{
// virtual function in derived class may be undefined as long as
// the derived class is not instantiated
public: void vf();
};

main()
{
B b, *pb;
D *pd; // instantiation like "D d;" or "D *pd = new D;" causes link error
pb = &b; pb->vf();
pd = (D*)&b; pd->vf();
}
This is class B
This is class B
6.純虚関数は定義されていない(一度実現するともはや純虚関数ではない)
#include <iostream>
using namespace std;

// B is abstract class because its vf() is pure virtual function
class B
{
public: void virtual vf()=0;
};

// C is also abstract class because it inherits pure virtual function vf()
class C: public B
{
// "public: void vf();" here would change vf() to be non-pure virtual
// function and cause link error when D instantiates
// but if D derives from B directly as "class D: public B" then it is OK
};

// D is not abstract class because its vf() is defined and no longer pure virtual function
class D: public C
{
public: void vf() { cout << "This is class D" << endl; }
};

// E is not abstract class and has another implementation of vf()
class E: public D
{
public: void vf() { cout << "This is class E" << endl; }
};

main()
{
B *pb; // instantiation like "B b;" or "B *pb = new B;" causes link error
C *pc; // instantiation like "C c;" or "C *pc = new C;" causes link error
D d, *pd;
E e, *pe;
pb = &d; pb->vf();
pc = &e; pc->vf();
pd = &e; pd->vf();
pe = (E*)&d; pe->vf();
}
This is class D
This is class E
This is class E
This is class D
3+4+5+6をまとめると、すべての関数に対して、定義しない=>呼び出しができない;純虚関数:定義しない=>クラスはインスタンス化できません.非純粋な虚関数:定義しない=>クラスとその派生クラスはインスタンス化できません