ทำไมฉันทำไม่ได้
class A
{
public:
int a, b;
};
class B : public A
{
B() : A(), a(0), b(0)
{
}
};
ทำไมฉันทำไม่ได้
class A
{
public:
int a, b;
};
class B : public A
{
B() : A(), a(0), b(0)
{
}
};
คำตอบ:
คุณไม่สามารถเริ่มต้นa
และb
ในเพราะพวกเขาไม่ได้เป็นสมาชิกของB
B
พวกเขาเป็นสมาชิกA
ดังนั้นจึงA
สามารถเริ่มต้นได้เท่านั้น คุณสามารถทำให้เป็นสาธารณะจากนั้นทำการมอบหมายได้B
แต่นั่นไม่ใช่ตัวเลือกที่แนะนำเนื่องจากจะทำลายการห่อหุ้ม ให้สร้างคอนสตรัคเตอร์A
เพื่ออนุญาตB
(หรือคลาสย่อยใด ๆ ของA
) เพื่อเตรียมใช้งาน:
class A
{
protected:
A(int a, int b) : a(a), b(b) {} // Accessible to derived classes
// Change "protected" to "public" to allow others to instantiate A.
private:
int a, b; // Keep these variables private in A
};
class B : public A
{
public:
B() : A(0, 0) // Calls A's constructor, initializing a and b in A to 0.
{
}
};
a
และb
เข้าได้B::B()
เนื่องจากเป็นแบบส่วนตัว class B
คุณไม่สามารถเริ่มต้นพวกเขาเพราะพวกเขาไม่ได้เป็นสมาชิกของ ถ้าคุณทำให้พวกเขาได้รับการป้องกันสาธารณะหรือคุณอาจจะกำหนดB::B()
ไว้ในร่างกายของ
a
and b
... " และเปลี่ยนเป็น "You can't initialize ... " โดยไม่แน่ใจว่าประโยคที่เหลือนั้นสมเหตุสมผล แก้ไขโพสต์แล้ว
ทิ้งความจริงที่ว่าพวกเขาเป็นprivate
ตั้งแต่a
และb
เป็นสมาชิกของA
พวกเขาถูกกำหนดให้เริ่มต้นโดยA
ผู้สร้างไม่ใช่โดยผู้สร้างของคลาสอื่น ๆ (ได้มาหรือไม่)
ลอง:
class A
{
int a, b;
protected: // or public:
A(int a, int b): a(a), b(b) {}
};
class B : public A
{
B() : A(0, 0) {}
};
อย่างไรก็ตามไม่มีใครระบุวิธีที่ง่ายที่สุด:
class A
{
public:
int a, b;
};
class B : public A
{
B()
{
a = 0;
b = 0;
}
};
คุณไม่สามารถเข้าถึงสมาชิกพื้นฐานในรายการตัวเริ่มต้นได้ แต่ตัวสร้างเองเช่นเดียวกับเมธอดสมาชิกอื่น ๆ สามารถเข้าถึงpublic
และprotected
สมาชิกของคลาสพื้นฐานได้
B
มีการจัดสรรอินสแตนซ์จากนั้นจะถูกกำหนดไว้ภายในตัวB
สร้าง แต่ฉันก็คิดว่าคอมไพเลอร์ยังคงสามารถเพิ่มประสิทธิภาพนี้ได้
class A
เราไม่สามารถพึ่งพาa
และb
เริ่มต้นได้ class C : public A
ตัวอย่างเช่นการดำเนินการใด ๆอาจลืมโทรa=0;
และปล่อยไว้โดยa
ไม่ได้เริ่มต้น
class A { int a = 0;};
) หรือในตัวสร้างของคลาสฐาน คลาสย่อยยังคงสามารถกำหนดค่าเริ่มต้นใหม่ในตัวสร้างได้ตามต้องการ
# include<stdio.h>
# include<iostream>
# include<conio.h>
using namespace std;
class Base{
public:
Base(int i, float f, double d): i(i), f(f), d(d)
{
}
virtual void Show()=0;
protected:
int i;
float f;
double d;
};
class Derived: public Base{
public:
Derived(int i, float f, double d): Base( i, f, d)
{
}
void Show()
{
cout<< "int i = "<<i<<endl<<"float f = "<<f<<endl <<"double d = "<<d<<endl;
}
};
int main(){
Base * b = new Derived(10, 1.2, 3.89);
b->Show();
return 0;
}
เป็นตัวอย่างการทำงานในกรณีที่คุณต้องการเริ่มต้นสมาชิกข้อมูลคลาสฐานที่มีอยู่ในออบเจ็กต์คลาสที่ได้รับมาในขณะที่คุณต้องการส่งค่าเหล่านี้เชื่อมต่อผ่านการเรียกตัวสร้างคลาสที่ได้รับ
ขณะนี้เป็นประโยชน์ในกรณีที่หายาก (ถ้าที่ไม่ได้กรณีภาษาที่จะได้รับอนุญาตได้โดยตรง) ใช้เวลาดูที่ฐานจากสมาชิกสำนวน ไม่ใช่วิธีการแก้ปัญหาโดยไม่ต้องใช้รหัสคุณต้องเพิ่มการสืบทอดอีกชั้นหนึ่ง แต่จะทำให้งานสำเร็จ เพื่อหลีกเลี่ยงรหัสสำเร็จรูปคุณสามารถใช้การเพิ่มประสิทธิภาพ
ทำไมถึงทำไม่ได้ เนื่องจากภาษาไม่อนุญาตให้คุณเริ่มต้นคลาสพื้นฐาน 'สมาชิกในรายการเริ่มต้นของคลาสที่ได้รับ'
คุณจะทำสิ่งนี้ได้อย่างไร? แบบนี้:
class A
{
public:
A(int a, int b) : a_(a), b_(b) {};
int a_, b_;
};
class B : public A
{
public:
B() : A(0,0)
{
}
};
หากคุณไม่ระบุการเปิดเผยสำหรับสมาชิกชั้นเรียนค่าเริ่มต้นจะเป็น "ส่วนตัว" คุณควรกำหนดให้สมาชิกของคุณเป็นส่วนตัวหรือได้รับการปกป้องหากคุณต้องการเข้าถึงสมาชิกในคลาสย่อย
คลาสรวมเช่น A ในตัวอย่างของคุณ (*) ต้องให้สมาชิกเป็นสาธารณะและไม่มีตัวสร้างที่ผู้ใช้กำหนดเอง พวกเขาจะ intialized กับรายการ initializer เช่นหรือในกรณีของคุณA a {0,0};
B() : A({0,0}){}
สมาชิกของคลาสการรวมฐานไม่สามารถเริ่มต้นทีละตัวในตัวสร้างของคลาสที่ได้รับ
(*) เพื่อให้ถูกต้องตามที่กล่าวไว้อย่างถูกต้องต้นฉบับclass A
ไม่ได้เป็นการรวมเนื่องจากสมาชิกส่วนตัวที่ไม่คงที่