-
أوجه التشابه والاختلاف بين C++ وJava
1. المؤشر ★★★★★
توفر المؤشرات في لغة C++ مرونة كبيرة، ولكن المرونة أيضًا تجلب مخاطر. قد يؤدي التشغيل غير الصحيح للمؤشرات إلى حدوث مشكلات مثل تسرب الذاكرة أو المؤشرات المتدلية.
جافا تلغي المؤشرات. ولكن في الواقع، يمكن فهم أسماء جميع أنواع البيانات المرجعية المعلنة في Java على أنها مؤشر. يتم تخزين الاسم في ذاكرة المكدس ويشير إلى المساحة المفتوحة الجديدة في الذاكرة.
يحب:
كثافة العمليات [] صفيف = كثافة العمليات الجديدة [10]
توجد مصفوفة اسم المصفوفة الصحيحة في ذاكرة المكدس، ويتم فتح مساحة 10*4 بايت في ذاكرة الكومة، وتشير المصفوفة إلى كتلة الذاكرة.
يمكن فهم المصفوفة على أنها مؤشر، والعنوان المخزن فيها هو المساحة التي تم إنشاؤها بواسطة new.
يحب:
شخص الصف{
…
}
الشخص ع = شخص جديد ()؛
يتم فتح اسم الكائن p في ذاكرة المكدس، ويستخدم الجديد لفتح مساحة في ذاكرة الكومة للكائن. يشير اسم الكائن p إلى ذاكرة الكومة.
ولكن في الواقع، الاسم ليس مثل المؤشر في C++، خاصة عند تمرير المعلمات.
ذكرت Java أن تمرير المعلمة يكون حسب القيمة.
ولكن عند استخدام نوع البيانات المرجعية كمعلمة دالة، عند تمرير كائن مُعلن p1، يتم إنشاء نسخة من الكائن p2 بالفعل، ويشير هذا p2 إلى p1، لذلك عند استدعاء أعضاء p1 إلى p2، يمكن ذلك اكتمل التعديل، وانتظر حتى اكتمال استدعاء الوظيفة، واحتفظ بالتعديل. يحب:
شخص الصف{
اسم السلسلة العامة؛
العمر العام ;
شخص عام (اسم السلسلة، العمر int) {
this.name = name;
this.age = age;
}
}
اختبار الطبقة العامة {
public static void main(String[] args){
Person p = new Person("Zhang San", 10);
System.out.println("قبل التعديل-->الاسم: "+ p.name+"، العمر: "+p.age);
ChangePro(p); // يتم تمرير الكائن p، ويتم إنشاء نسخة من p بافتراض أنه p1، والذي يشير إلى p. // من خلال هذه النسخة p1، يمكن استدعاء أعضاء p.
System.out.println("بعد التعديل-->الاسم: "+ p.name+"، العمر: "+p.age);
}
public static void ChangePro(Person p){ // يمكن استدعاء أعضاء الكائن الأصلي من خلال النسخة
p.name = "李思";
صفحة العمر = 30؛
}
}
نتيجة:
قبل التعديل-->الاسم: تشانغ سان، العمر: 10 سنوات
بعد التعديل-->الاسم: لي سي، العمر: 30 عامًا
ولكن عندما تقوم بتمرير p1، يتم إنشاء نسخة من p2، ومن الواضح أن محاولة تغيير الإشارة من p1 إلى p2 أمر مستحيل. في هذا الوقت، يتم تغيير الإشارة إلى p2 فقط بعد اكتمال استدعاء الوظيفة من p1 يبقى دون تغيير. يحب:
شخص الصف{
اسم السلسلة العامة؛
العمر العام ;
شخص عام (اسم السلسلة، العمر int) {
this.name = name;
this.age = age;
}
}
اختبار الطبقة العامة {
public static void main(String[] args){
Person p = new Person("Zhang San", 10);
System.out.println("قبل التعديل-->الاسم: "+ p.name+"، العمر: "+p.age);
ChangeObj(p); // تم تمرير الكائن p، وهو نسخة من p. // في الوظيفة، يتم تغيير مؤشر هذه النسخة فقط.
System.out.println("بعد التعديل-->الاسم: "+ p.name+"، العمر: "+p.age);
}
public static Person newP = new Person("李思", 30);
تغيير الفراغ الثابت العامObj (الشخص ع) {
p = newP; // محاولة تغيير المؤشر، ولكن ما يتغير فعليًا هو مؤشر النسخة.
// بعد انتهاء الوظيفة، لن يتغير مؤشر الكائن الأصلي
}
}
نتيجة:
قبل التعديل-->الاسم: تشانغ سان، العمر: 10 سنوات
بعد التعديل-->الاسم: تشانغ سان، العمر: 10 سنوات
2. تخصيص الذاكرة الديناميكية
في C++، يتم استخدام الجديد والحذف لتخصيص الذاكرة وإعادة تدويرها ديناميكيًا. الجديد هو فتح مساحة على ذاكرة الكومة بعد استخدام الذاكرة، ويجب استخدام الحذف يدويًا لإعادة تدويرها.
طالما تم الإعلان عن نوع بيانات مرجعي في Java، يجب استخدام جديد لفتح مساحة الذاكرة قبل الاستخدام. ولكن بعد وفاة الكائن، ليست هناك حاجة لاستعادة الذاكرة يدويًا. ستعمل آلية إعادة تدوير الذاكرة الخاصة بـ Java على إعادة تدوير الكائنات المهملة تلقائيًا (تشير ما يسمى بالكائنات المهملة إلى ذاكرة الكائن المفتوحة مسبقًا، والتي لم تعد يتم الرجوع إليها بواسطة ذاكرة المكدس). بالطبع، يمكن أيضًا إجراء إعادة التدوير اليدوية من خلال طريقة System.gc().
3. المدمر
وظيفة destructor C++ (لا توجد معلمات، لا توجد قيمة إرجاع) هي تحرير مساحة الذاكرة المخصصة ديناميكيًا في المنشئ، أي الاتصال (يمكن استدعاء هذه المكالمة من خلال object.destructor، أو يمكن للنظام الانتظار تلقائيًا حتى ينتهي عمر الكائن Call) المدمر.
لا يوجد مدمر في Java، ويتم إعادة تدوير الكائنات المهملة تلقائيًا من خلال آلية جمع البيانات المهملة. ومع ذلك، يمكنك تحقيق نفس تأثير المدمر في C++ عن طريق تجاوز طريقة fanalize() في فئة الكائن. عندما يتم تدمير الكائن يدويًا أو تلقائيًا، سيتم استدعاء طريقة fanalize() تلقائيًا.
4. المحتويات في الفصول الفارغة
يجب أن تحتوي الفئة الفارغة لـ C++ على 4 وظائف: المُنشئ الافتراضي، والمدمر الافتراضي، ومنشئ النسخ الافتراضي.
تتضمن فئات Java الفارغة: المنشئ الافتراضي، والطرق الموروثة من فئة الكائن، مثل
السمات الافتراضية في الفئات هناك ثلاثة أنواع من أذونات وصول الأعضاء في فئات C++: عامة>محمية>خاصة. إذا لم يتم الإعلان عنه، يكون الإذن الافتراضي خاصًا.
هناك أربعة أنواع من أذونات وصول الأعضاء في فئات Java: عام>محمي>افتراضي>خاص. الافتراضي هو الإذن الافتراضي.
5. تنفيذ وظائف الأعضاء في الفصول الدراسية
ومن المعتاد في C++. h تم الإعلان عن الوظيفة في فئة ملف الرأس خارج الفئة. لتنفيذ الوظيفة في ملف cpp، قم بتضمين ملف الرأس.
يحب:
//demo.h
شخص الصف{
عام:
متعة باطلة () ؛ // تم الإعلان عنها في الفصل
}
//demo.cpp
#تشمل "demo.h"
Void Person::fun(){ // التنفيذ خارج الفصل
. . . . // جسم التنفيذ
}
Java عبارة عن طريقة إعلان + تنفيذ في الفصل الدراسي. إذا لم يتم تنفيذها في الفصل الدراسي، فإن إضافة الكلمة الأساسية المجردة تعد طريقة مجردة.
يحب:
شخص الصف{
متعة الفراغ العام () {// الإعلان + التنفيذ في الفصل
. . . . // جسم التنفيذ
}
}
6. إنشاء مثيل للكائنات
شخص الصف{
خاص:
العمر الصحيح؛
عام:
شخص(){}
شخص (كثافة العمليات أ) {
العمر = أ ;
}
متعة باطلة (){….}
}
. . . . // بداية الوظيفة الرئيسية
Person p1; // يتم استدعاء المُنشئ بدون معلمات
الشخص p2(18); // اتصل بالمنشئ ذو المعلمات
p1.fun(); // استدعاء وظيفة العضو
p2.fun();
لإنشاء كائن في Java، يجب عليك استخدام الكلمة الأساسية الجديدة.
شخص الصف{
اسم سلسلة خاصة؛
عمر خاص ;
شخص عام (){}
شخص عام (اسم السلسلة، العمر int) {
this.name = name;
this.age = age;
}
متعة الفراغ العام () {…..}
}
. . . . . // بداية الوظيفة الرئيسية
الشخص p1 = فارغ؛
p1 = new Person(); // يجب عليك استخدام الكلمة الأساسية الجديدة لفتح مساحة الذاكرة واستدعاء المُنشئ بدون معلمات.
Person p2 = new Person("Zhang San", 18); // اتصل بالمنشئ ذو المعلمات.
p1.fun(); // طريقة الاتصال
p2.fun();
7. هذه الكلمة الرئيسية
يطلق عليه هذا المؤشر في لغة C++. عندما يتم إنشاء مثيل لكائن ما، سيتم إنشاء هذا المؤشر افتراضيًا للإشارة إلى هذا الكائن. ويستخدمه المترجم للتمييز بين الكائنات المختلفة من نفس الفئة. أي ككائن. عند استخدام وظيفة عضو، يمكنك معرفة الكائن من خلال هذا المؤشر، واستدعاء وظيفة العضو لتشغيل خصائص العضو للكائن.
هذا له ثلاثة استخدامات في Java:
1. يمثل السمات أو الأساليب في هذه الفئة. مثل هذا. الطريقة، هذا. ملكية.
2. يمثل الكائن الحالي.
3. استدعاء طريقة البناء لهذه الفئة. مثل هذا ()، هذا (المعلمة 1، المعلمة 2 ...).
[تشبه وظائف الاستخدام 1 و2 هذا المؤشر في لغة C++. 】
8. استدعاء أعضاء الكائن
يمرر C++ الكائنات. وظيفة العضو، أو مؤشر الفئة->وظيفة العضو للاتصال بها.
في Java، يمكنك تمرير الكائنات فقط. استدعاء وظيفة العضو.
يمكن تمرير أعضاء السمة الثابتة للاثنين مباشرة من خلال اسم الفئة. يتم استدعاء وظائف الأعضاء مباشرة.
9. الفئة الفرعية-->الفئة الأصلية، هناك شيء مشترك بين المعلمات التي يمررها المُنشئ: إذا لم يُشير المُنشئ في الفئة الفرعية بوضوح إلى مُنشئ الفئة الأصلية المطلوب الاتصال به، فسيقوم النظام افتراضيًا باستدعاء مُنشئ الفئة الأصلية بدون معلمات فصل. في الوقت نفسه، إذا حددت الفئة الأصل مُنشئًا بمعلمات، فمن الأفضل تحديد مُنشئ بدون معلمات.
شخص الصف{
خاص:
العمر الصحيح؛
عام:
شخص(){}
شخص (كثافة العمليات أ) {
العمر = أ ;
}
}
طالب الصف: شخص عام{
خاص:
درجة كثافة العمليات؛
عام:
Student(int a, int s):Person(a){ // انتقل إلى مُنشئ الفصل الأصلي
النتيجة = ق؛
}
}
شخص الصف{
اسم سلسلة خاصة؛
عمر خاص ;
شخص عام (){}
شخص عام (اسم السلسلة، العمر int) {
this.name = name;
this.age = age;
}
}
طالب الفصل يمتد الشخص {
درجة كثافة العمليات الخاصة؛
الطالب العام (اسم السلسلة، العمر int، النتيجة int) {
super(name,age); // انتقل إلى مُنشئ الفئة الأصل
this.score = Score;
}
}
10. تعدد الأشكال
يجب تحقيق تعدد الأشكال في لغة C++ من خلال [وظيفة افتراضية أو وظيفة افتراضية خالصة + تغطية فئة فرعية للوظيفة الافتراضية أو وظيفة افتراضية خالصة].
يتم الإعلان عن الوظائف الافتراضية باستخدام Virtual،
يحب:
متعة باطلة افتراضية () ؛ // الإعلان داخل الفصل
اسم فئة باطلة: fun() {....}// تنفيذ خارج الفئة
تستخدم Java الفئات الفرعية لتجاوز الأساليب العادية في الفئات الأصلية العادية، والفئات الفرعية لتجاوز الأساليب العادية أو الأساليب المجردة في الفئات المجردة، والفئات الفرعية لتجاوز الأساليب المجردة في الواجهات. + تحويل للأعلى.
يتم الإعلان عن الأساليب المجردة بالملخص وليس لها أي تطبيق للمحتوى.
يحب:
مجردة باطلة متعة () // لا يوجد تنفيذ داخل الفصل
11. الطبقات المجردة لا يمكن لأي فئة مجردة إنشاء مثيل للكائنات. الوظائف الافتراضية البحتة والأساليب المجردة لها مفاهيم مماثلة ووظائف مماثلة.
ويمكن القول أيضًا أن هناك فئات مجردة في لغة C++، وهي فئات ذات وظائف افتراضية خالصة.
الوظيفة الافتراضية الخالصة هي وظيفة افتراضية بدون تنفيذ محتوى و"=0"، ولا يمكنها إنشاء مثيل للكائنات.
يحب:
Virtual void fun() = 0; // تم الإعلان عنه كـ =0 داخل الفصل، ولم يتم تنفيذه خارج الفصل.
الفئة المجردة في Java هي فئة تم الإعلان عنها باستخدام الكلمة الأساسية المجردة وتحتوي على طرق مجردة. لا يمكن إنشاء مثيل للكائن.
الواجهة في Java هي فئة خاصة، أو فئة مجردة خاصة. وهو يتألف من جميع الثوابت الثابتة والوظائف المجردة.
12. حقوق الوصول
يستخدم C++ ثلاث طرق وراثة لتغيير حقوق الوصول للأعضاء بين الفئات الفرعية والفئات الأصلية.
طالب الصف: شخص عام{
عام:
. . . . . .
خاص:
. . . . . .
};
عامل الفصل: شخص محمي{
عام:
. . . . . .
خاص:
. . . . . .
};
مزارع الطبقة: شخص خاص {
عام:
. . . . . .
خاص:
. . . . . .
};
تنفذ Java أذونات الوصول للأعضاء بين الفئات المختلفة من خلال آلية الحزمة.
الحزمة org.tyut.a
شخص الصف{
خاص…..
خاص……
عام…….
عام…
}
الحزمة org.tuyt.b
شخص الصف{
خاص…..
خاص……
عام…….
عام…
}
الحزمة org.tuyt.c
شخص الصف{
خاص…..
خاص……
عام…….
عام…
}
13. فكرة المعالجة المسبقة لـ C++ وحزمة استيراد Java هي نفسها: عندما تريد استخدام فئة أخرى غير الفئة الحالية،
في لغة C++، استخدم توجيه الترجمة المسبقة #include قبل تعريف الفئة لتضمين مكتبة الفئة المراد تضمينها.
تستخدم مكتبات الفئة القياسية الأقواس الزاوية < > بدون h. استخدم علامات الاقتباس المزدوجة "" مع h في مكتبة الفئات المخصصة، وسيتم البحث عنها من المسار الحالي أولاً.
يحب:
#تشمل <iostream>
#تشمل "demo.h"
في Java، لاستيراد الفئة التي تريد استخدامها، استخدم أمر الاستيراد وحدد الحزمة التي يوجد بها الفئة.
يحب:
استيراد جافا. لانج. *؛
منظمة الاستيراد. tyut. *؛