C++クラスの空のポインターは、メンバー関数のコードを呼び出します。
クラスの実例はメンバー関数を呼び出す原理です。
実際には、オブジェクトのインスタンスまたはポインタのインスタンスを介して呼び出しても、実際には、下の階の呼び出しのプロセスは同じであり、現在のオブジェクトのポインタをパラメータとして呼び出しられたメンバー関数に渡すことである。以下の関連実例コードによって検証される:
実験のC++コード
ソースコードとコンパイルコードの対比を通じて、実はメンバー関数とクラスの実例はバインディング関係がないので、メンバー関数はクラスに属しています。メモリの中には有効なメモリアドレスだけがあります。メンバ関数については、インスタンスが必要であり、レジスタECXを介して渡される。
ここで考えさせてください。なぜスタックを通して伝達しないですか?
まず、スタックはメモリに位置していますが、レジスタはCPUに位置しています。この2つの読み書き速度は違います。これは効率の最適化です。また、約束が現在のメンバー関数の中にある場合は、ECXレジスタを変更しないと良いです。
しかし、スタックを使用して転送する場合、スタックはダイナミックメモリ空間であるため、現在のインスタンスのアドレスを追跡して維持するのに不便であり、たとえEBPとESPを使用してメンテナンスしても、オフセット量を加算する必要があり、これは読み書き効率に負担をかける。メンテナンスがうまくいかないと、データが乱れます。ここは全部個人分析です。間違いがあれば指摘してもいいです。
タイトルを返す
したがって、タイトルに戻ります。クラスの空のポインタがメンバー関数を呼び出したら、コンパイルが通ります。次に運行中に、二つの状況に分けます。
一、呼び出しられたメンバー関数では、現在のインスタンスのメンバー変数を呼び出さない場合、プログラムは正常に実行されます。
最後に発散して考える
その中の一つの言叶を思い出します。メンバー関数はクラスに属しています。実例ではなく、あなたの思考を引き起こしますか?クラスの静态関数もクラスに属しています。上のコード:
締め括りをつける
面接の時に聞かれました。自分でできますが、はっきり答えられないのも罪です。ここでまとめます。
ここでは、C++クラスの空のポインターは、メンバー関数を呼び出す記事を紹介します。より多くの関連C++クラスの空のポインターは、メンバー関数の内容を呼び出します。私たちの以前の記事を検索したり、次の関連記事を見たりしてください。これからもよろしくお願いします。
実際には、オブジェクトのインスタンスまたはポインタのインスタンスを介して呼び出しても、実際には、下の階の呼び出しのプロセスは同じであり、現在のオブジェクトのポインタをパラメータとして呼び出しられたメンバー関数に渡すことである。以下の関連実例コードによって検証される:
実験のC++コード
class Student
{
private:
int age;
public:
Student() {}
Student(int age) : age(age) {}
int getAge() { return this->age; }
};
int main(int argc, char const *argv[])
{
Student s(10);
int age = s.getAge();
Student* ps = new Student(10);
age = ps->getAge();
return 0;
}
VSL 2015デバッグ機能に基づく反アセンブリコード
int main(int argc, char const *argv[])
{
00A41860 push ebp
00A41861 mov ebp,esp
00A41863 push 0FFFFFFFFh
00A41865 push 0A461D2h
00A4186A mov eax,dword ptr fs:[00000000h]
00A41870 push eax
00A41871 sub esp,104h
00A41877 push ebx
00A41878 push esi
00A41879 push edi
00A4187A lea edi,[ebp-110h]
00A41880 mov ecx,41h
00A41885 mov eax,0CCCCCCCCh
00A4188A rep stos dword ptr es:[edi]
00A4188C mov eax,dword ptr [__security_cookie (0A4B004h)]
00A41891 xor eax,ebp
00A41893 mov dword ptr [ebp-10h],eax
00A41896 push eax
00A41897 lea eax,[ebp-0Ch]
00A4189A mov dword ptr fs:[00000000h],eax
Student s(10);
00A418A0 push 0Ah /* : 10 */
00A418A2 lea ecx,[s] /* s , ECX*/
00A418A5 call Student::Student (0A4103Ch) /* 0A4103Ch */
int age = s.getAge();
00A418AA lea ecx,[s] /* s , ECX*/
00A418AD call Student::getAge (0A412D5h) /* 0A412D5h */
00A418B2 mov dword ptr [age],eax /* age*/
Student* ps = new Student(10);
00A418B5 push 4 /* , int , 4 (32 )*/
00A418B7 call operator new (0A412A3h) /* , C malloc */
00A418BC add esp,4 /* 4 , operator new */
00A418BF mov dword ptr [ebp-108h],eax /*eax , ptr [ebp-108h] */
00A418C5 mov dword ptr [ebp-4],0
00A418CC cmp dword ptr [ebp-108h],0
00A418D3 je main+8Ah (0A418EAh) /* , 0, , 0A418EAh*/
00A418D5 push 0Ah /* : 10*/
00A418D7 mov ecx,dword ptr [ebp-108h] /* ps ECX*/
00A418DD call Student::Student (0A4103Ch) /* 0A4103Ch */
00A418E2 mov dword ptr [ebp-110h],eax
00A418E8 jmp main+94h (0A418F4h)
00A418EA mov dword ptr [ebp-110h],0
00A418F4 mov eax,dword ptr [ebp-110h]
00A418FA mov dword ptr [ebp-0FCh],eax
00A41900 mov dword ptr [ebp-4],0FFFFFFFFh
00A41907 mov ecx,dword ptr [ebp-0FCh]
00A4190D mov dword ptr [ps],ecx
age = ps->getAge();
00A41910 mov ecx,dword ptr [ps] /* s ECX*/
00A41913 call Student::getAge (0A412D5h) /* 0A412D5h */
age = ps->getAge();
00A41918 mov dword ptr [age],eax
return 0;
00A4191B xor eax,eax
}
分析ソースコードとコンパイルコードの対比を通じて、実はメンバー関数とクラスの実例はバインディング関係がないので、メンバー関数はクラスに属しています。メモリの中には有効なメモリアドレスだけがあります。メンバ関数については、インスタンスが必要であり、レジスタECXを介して渡される。
ここで考えさせてください。なぜスタックを通して伝達しないですか?
まず、スタックはメモリに位置していますが、レジスタはCPUに位置しています。この2つの読み書き速度は違います。これは効率の最適化です。また、約束が現在のメンバー関数の中にある場合は、ECXレジスタを変更しないと良いです。
しかし、スタックを使用して転送する場合、スタックはダイナミックメモリ空間であるため、現在のインスタンスのアドレスを追跡して維持するのに不便であり、たとえEBPとESPを使用してメンテナンスしても、オフセット量を加算する必要があり、これは読み書き効率に負担をかける。メンテナンスがうまくいかないと、データが乱れます。ここは全部個人分析です。間違いがあれば指摘してもいいです。
タイトルを返す
したがって、タイトルに戻ります。クラスの空のポインタがメンバー関数を呼び出したら、コンパイルが通ります。次に運行中に、二つの状況に分けます。
一、呼び出しられたメンバー関数では、現在のインスタンスのメンバー変数を呼び出さない場合、プログラムは正常に実行されます。
class Student
{
private:
int age;
public:
Student() {}
Student(int age) : age(age) {}
void eat() {}
};
int main(int argc, char const *argv[])
{
Student* ps = nullptr;
ps->eat();
return 0;
}
二、呼び出されたメンバー関数では、現在のインスタンスのメンバー変数を読むためにthisポインタを使用した場合、まず呼び出しはメンバー関数が成功的に呼び出され、コードの実行はメンバー関数の領空に入りましたが、コードが現在のインスタンスを読み書きするメンバー変数に実行されるとメモリアクセスが異常になります。最後に発散して考える
その中の一つの言叶を思い出します。メンバー関数はクラスに属しています。実例ではなく、あなたの思考を引き起こしますか?クラスの静态関数もクラスに属しています。上のコード:
#include <iostream>
using namespace std;
class Student
{
private:
int age;
public:
Student() {}
Student(int age) : age(age) {}
static int classtime() {
return 9;
}
void eat() {}
};
int main(int argc, char const *argv[])
{
Student* ps = nullptr;
int time = ps->classtime();
cout << time << endl;
return 0;
}
実験を通してこのコードは成功的に実行できることがわかった。原理は上に述べましたが、ここでは詳しく説明しません。主な点はクラスの静的関数が特定のインスタンスのメンバデータに絶対に動作しないため、このような呼び出しは安全である。実際のプログラミングでは、この方法は使えないでしょう。締め括りをつける
面接の時に聞かれました。自分でできますが、はっきり答えられないのも罪です。ここでまとめます。
ここでは、C++クラスの空のポインターは、メンバー関数を呼び出す記事を紹介します。より多くの関連C++クラスの空のポインターは、メンバー関数の内容を呼び出します。私たちの以前の記事を検索したり、次の関連記事を見たりしてください。これからもよろしくお願いします。