***
虚関数:虚関数は関数ポインタに相当し、4バイト(32ビット)を占有し、クラス内の虚関数は4バイトを占有し、そのメンバー関数はクラスのメモリを占有しない.
ベースクラスは虚関数を定義し、サブクラスの同名関数を優先的に呼び出し、虚関数を上書きします.ベースクラスポインタは、異なる派生オブジェクトにアクセスし、異なるメソッドを呼び出します.
注意:1.虚関数はクラスのメンバー関数でなければなりません
2.友元関数を虚関数として説明することはできませんが、虚関数は別のクラスの友元とすることができます.
3.構造関数は虚関数であってもよいが、構造関数は虚関数であってはならない.
親オブジェクトポインタが派生クラスオブジェクトを指す場合、サブクラス構造関数が自動的に呼び出されます.
構造関数が虚関数の場合、派生クラスとベースクラスの構造関数が自動的に呼び出されます.
ダミー関数のリロード特性:
1.派生クラスの関数属性は、ベースクラスと同じである必要があります.
2.戻りタイプは同じでなければなりません.そうしないと、エラーが再ロードされます.
3.プロトタイプが異なり、関数名が同じだけで、虚関数の特性が失われます.
純虚関数関数抽象クラス.
1.基底クラスでは虚関数を説明する純虚関数ですが、基底クラスでは定義されておらず、派生クラスごとに独自のバージョンを定義する必要があります.
2.純粋な関数は派生クラスの共通インタフェースである.
3.純虚関数を持つベースクラス抽象クラス.抽象クラスはインスタンス化できず,派生によりインスタンス化する.
4.抽象クラスは、関数のパラメータや戻り値のタイプには使用できませんが、抽象クラスポインタは使用できます.
5.虚関数テーブルはコンパイラのコード領域にあり、虚関数ポインタは虚関数テーブルを指し、1つ以上の虚関数は4バイトを占有する.
ヘテロチェーンテーブル:ベースクラスを利用して派生クラスポインタの特徴を格納し、ベースクラスポインタで派生クラスのアドレスを受信することができる.ベースクラスポインタを使用して、異なる派生クラスオブジェクトを接続するダイナミックチェーンテーブルを生成します.各ノードポインタは、クラス階層内の異なる派生クラスオブジェクトを指します.ノードタイプの異なるチェーンテーブル.
ベースクラスは虚関数を定義し、サブクラスの同名関数を優先的に呼び出し、虚関数を上書きします.ベースクラスポインタは、異なる派生オブジェクトにアクセスし、異なるメソッドを呼び出します.
注意:1.虚関数はクラスのメンバー関数でなければなりません
2.友元関数を虚関数として説明することはできませんが、虚関数は別のクラスの友元とすることができます.
3.構造関数は虚関数であってもよいが、構造関数は虚関数であってはならない.
#include
using namespace std;
class base1
{
public:
virtual int run() = 0;
virtual double go() = 0;
};
class base2
{
public:
virtual void run()
{
}
virtual void go()
{
}
};
void main()
{
cout << sizeof(base1)<
親オブジェクトポインタが派生クラスオブジェクトを指す場合、サブクラス構造関数が自動的に呼び出されます.
#include
class base
{
public:
virtual void name() //
{
std::cout << "base" << std::endl;
std::cout << "x=" << x << std::endl;
}
int x;
base(int a) :x(a)
{
}
};
class zi :
public base
{
public:
void name()
{
std::cout << "zi" << std::endl;
std::cout << "x=" << x << "y=" << y<< std::endl;
}
int y;
zi(int a,int b) :base(a),y(b)
{
}
};
class sun :
public zi
{
public:
void name()
{
std::cout << "sun" << std::endl;
std::cout << "x=" << x << "y=" << y << "z=" << z << std::endl;
}
int z;
sun(int a,int b,int c) :zi(a,b),z(c)
{
}
};
//
void main()
{
base p1(1);
zi p2(2,3);
sun p3(4,5,6);
base *p;
p = &p1; //
p->name(); //
p = &p2; //
p->name();
p = &p3;//
p->name();
std::cout << sizeof(base) << std::endl;
std::cin.get();
}
void main1()
{
base *pb = new base(1);
pb->name();
zi *pz = new zi(2,3);
pz->name();
sun *ps = new sun(4,5,6);
ps->name();
zi *p =static_cast(pb) ;
p->name();
std::cin.get();
}
構造関数が虚関数の場合、派生クラスとベースクラスの構造関数が自動的に呼び出されます.
#include
class my
{
public:
//virtual
my()
{
std::cout << "my creat" << std::endl;
}
virtual
~my() // , ,
{
std::cout << "my delete" << std::endl;
}
};
class myzi :public my
{
public:
myzi()
{
std::cout << "myzi creat" << std::endl;
}
~myzi()
{
std::cout << "myzi delete" << std::endl;
}
};
void run()
{
/*my *p = new my;
delete p;*/
my *p1 = new myzi;
delete p1;
}
void main3()
{
run();
std::cout << "hello world!" << std::endl;
std::cin.get();
}
ダミー関数のリロード特性:
1.派生クラスの関数属性は、ベースクラスと同じである必要があります.
2.戻りタイプは同じでなければなりません.そうしないと、エラーが再ロードされます.
3.プロトタイプが異なり、関数名が同じだけで、虚関数の特性が失われます.
#include
class A
{
public:
virtual int run()
{
return 1;
}
virtual int go()
{
return 0;
}
};
class B :public A
{
public:
virtual int run()
{
return 2;
}
//void go()
//{
// }
};
void main4()
{
B c;
std::cout<<:run std::cin.get=""/>
純虚関数関数抽象クラス.
1.基底クラスでは虚関数を説明する純虚関数ですが、基底クラスでは定義されておらず、派生クラスごとに独自のバージョンを定義する必要があります.
2.純粋な関数は派生クラスの共通インタフェースである.
3.純虚関数を持つベースクラス抽象クラス.抽象クラスはインスタンス化できず,派生によりインスタンス化する.
4.抽象クラスは、関数のパラメータや戻り値のタイプには使用できませんが、抽象クラスポインタは使用できます.
5.虚関数テーブルはコンパイラのコード領域にあり、虚関数ポインタは虚関数テーブルを指し、1つ以上の虚関数は4バイトを占有する.
#include
//
class A
{
public:
int a;
virtual void show() = 0;
virtual void go() = 0;//
};
class B :public A
{
public:
int num;
void show()
{
std::cout << "B show()" << std::endl;
}
void go()
{
std::cout << "B go()" << std::endl;
}
};
A *test()
{
A *p(nullptr);
return p;
}
void main5()
{
B c;
//A aa;// , ;
A *p;
c.go();
c.show();
std::cin.get();
}
ヘテロチェーンテーブル:ベースクラスを利用して派生クラスポインタの特徴を格納し、ベースクラスポインタで派生クラスのアドレスを受信することができる.ベースクラスポインタを使用して、異なる派生クラスオブジェクトを接続するダイナミックチェーンテーブルを生成します.各ノードポインタは、クラス階層内の異なる派生クラスオブジェクトを指します.ノードタイプの異なるチェーンテーブル.
#include
#include
#include
using namespace std;
class base
{
public:
virtual void show() = 0;
};
class linknode
{
public:
base *p; //
linknode *pnext; //
};
class A :public base
{
public:
void show()
{
cout << "class A
";
}
};
class B :public base
{
public:
void show()
{
cout << "class B
";
}
};
class C :public base
{
public:
void show()
{
cout << "class C
";
}
};
class D:public base
{
public:
void show()
{
cout << "class D
";
}
};
void showall(linknode *phead)
{
while (phead != NULL)
{
phead->p->show();
phead = phead->pnext;
}
}
void add(linknode *phead, base *p)
{
linknode *ptemp = phead;
if (ptemp == NULL)
{
ptemp->p = p;
ptemp->pnext = NULL;
}
else
{
while (ptemp->pnext != NULL)
{
ptemp = ptemp->pnext;
}
linknode *padd = new linknode; // ,
padd->p = p;
padd->pnext = NULL;
ptemp->pnext = padd; //
}
}
void main()
{
linknode *phead;
linknode node1, node2, node3;
A a1,a2,a3;
B b1,b2,b3;
C c1,c2,c3;
D d1;
phead = &node1; //
node1.pnext = &node2;
node2.pnext = &node3;
node3.pnext = NULL;
node1.p = &a1; //
node2.p = &b1;
node3.p = &c1;
showall(phead);
add(phead,&d1);
showall(phead);
cin.get();
}