'ฟังก์ชั่นคงที่' มีการใช้เมื่อใด


24

ตกลงฉันได้เรียนรู้ว่าฟังก์ชั่นคงที่คืออะไร แต่ฉันยังไม่เห็นว่าทำไมพวกเขาจึงมีประโยชน์มากกว่าฟังก์ชั่นสมาชิกส่วนตัว นี่อาจเป็นคำถามใหม่ที่นี่ แต่ทำไมไม่แทนที่ฟังก์ชั่นสมาชิกส่วนตัวทั้งหมดด้วยฟังก์ชั่นสแตติกแทน?


1
ไม่ควรที่จะ "แทนที่ฟังก์ชั่นสแตติกทั้งหมดด้วยฟังก์ชันสมาชิกส่วนตัว" ขณะนี้คุณกำลังระบุว่าคุณไม่เห็นจุดของวิธีการคงที่และไปถามว่าทำไมเราไม่ใช้วิธีการเพิ่มเติม

5
"ฟังก์ชั่นคงที่" คืออะไร? ใน C ++ มีความหมายอย่างน้อยสองรายการ (และสุดท้ายที่ฉันดูแบบร่าง C ++ 11 พวกเขาต้องการลบประกาศเลิกใช้งานstaticเพื่อ จำกัด ฟังก์ชั่นในขอบเขตไฟล์
David Thornley

คุณหมายถึง "ฟังก์ชั่นคงที่" ในความหมายของฟังก์ชั่นฟรีคงขอบเขตไฟล์ใน C / C ++ หรือเป็น "ฟังก์ชั่น memenber คงที่ / วิธีการ"? มันแตกต่างกันมาก!
Jan Hudec

@JanHudec: ฉันคิดว่าการมีอยู่ของprivate memberเราอย่างปลอดภัยสามารถถือว่า OP ถามเกี่ยวกับแนวคิด OO และไม่มีเงื่อนงำเกี่ยวกับขอบเขตไฟล์คงที่
Matthieu M.

@ MatthieuM: ที่จริงแล้วการปรากฏตัวของ 'สมาชิกส่วนตัว' เป็นสิ่งที่ทำให้ฉันเชื่อว่าเขาหมายถึงฟังก์ชั่นคงที่ในความรู้สึก C ++ เนื่องจากฟังก์ชั่นคงที่ที่กำหนดขอบเขตของไฟล์และฟังก์ชั่นสมาชิกส่วนตัวเป็นสองสิ่งที่มีการใช้งานคล้ายกันมากใน C ++ ในขณะที่การแทนที่สมาชิกสแตติกสาธารณะด้วยสมาชิกที่ไม่คงที่ส่วนตัวนั้นไม่สมเหตุสมผล ขออภัย OP ดูเหมือนจะไม่ตอบสนอง
Jan Hudec

คำตอบ:


24

สมมติว่าคุณกำลังใช้OOPใช้ฟังก์ชั่นคงที่เมื่อไม่ได้ขึ้นอยู่กับสมาชิกของคลาส พวกเขายังคงเป็นส่วนตัวได้ แต่วิธีนี้ได้รับการปรับให้เหมาะสมเนื่องจากไม่ได้ขึ้นอยู่กับอินสแตนซ์ของวัตถุที่เกี่ยวข้อง

นอกเหนือจากข้างต้นฉันพบว่าฟังก์ชั่นคงที่มีประโยชน์เมื่อคุณไม่ต้องการสร้างอินสแตนซ์ของวัตถุเพียงเพื่อดำเนินการฟังก์ชั่นสาธารณะหนึ่งมัน นี่เป็นกรณีส่วนใหญ่สำหรับคลาสตัวช่วยที่มีฟังก์ชันสาธารณะเพื่อทำงานซ้ำและงานทั่วไป แต่ไม่จำเป็นต้องรักษาสถานะใด ๆ ระหว่างการโทร


ขอบคุณเบอร์นาร์ด Btw คุณรู้หรือไม่ว่าคอมไพเลอร์หมายถึง "ผูกเมธอดเข้ากับคลาส" หมายความว่าอย่างไร
Dark Templar

@Dark Templar: พูดไม่ได้หรอก นี่เฉพาะภาษาที่เจาะจงหรือไม่?
เบอร์นาร์ด

ฉันมีปัญหาเล็กน้อยกับคำนิยามของคุณ "พวกเขาไม่ได้ขึ้นอยู่กับสมาชิกชั้นเรียน" ฟังก์ชั่นสมาชิกคงไม่สามารถเข้าถึงสมาชิกที่ไม่ใช่แบบคงที่ใด ๆ แต่พวกเขาสามารถเข้าถึงสมาชิกแบบคงที่ สมาชิกแบบสแตติกเป็นสมาชิกของคลาส
newprint

@newprint: ถูกต้อง แต่นั่นไม่ใช่สิ่งที่ฉันพูด ฉันพูดเมื่อพวกเขาไม่ได้ขึ้นอยู่กับสมาชิกในชั้นเรียน การใช้สมาชิกแบบสแตติกนั้นเป็นเรื่องปกติหากจำเป็น แต่อาจไม่เป็นเช่นนั้นเสมอไป
เบอร์นาร์ด

8

ลองคำอธิบายที่ง่ายขึ้นกว่าด้านบน (คำอธิบายที่ดีมาก)

วัตถุคือรหัส + ข้อมูลตามปกติ วิธีการแบบคงที่จะใช้เมื่อคุณมีส่วน "รหัส" เท่านั้นที่จะจัดการกับ (ไม่มีข้อมูล / สถานะการรักษา (ยกเว้นสมาชิกข้อมูลแบบคงที่))


5

เพราะพวกเขาไม่ต้องการตัวอย่างและสามารถเปิดเผยต่อสาธารณะได้ สมมติว่าคุณต้องการฟังก์ชั่นในการรับส่วนร่วมที่ยิ่งใหญ่ที่สุด (GCD; มีประโยชน์มากสำหรับคลาสเศษส่วนและใช่นี่เป็นเพียงตัวอย่างง่ายๆ) มีจุดในการสร้างระดับของวัตถุที่มีวัตถุประสงค์ไม่เป็นก็คือว่าคุณสามารถมีตัวชี้คุณไม่จำเป็นที่จะต้องใช้ในการมิได้this gcdดังนั้นคุณใช้วิธีสแตติกสำหรับคลาสที่ใช้ GCD จริง ๆ (เช่นในคลาสเศษส่วน)

ถ้าหากมีเพียงวิธีการคงที่คุณกำลังทำผิด OOP และควรเปลี่ยนไปทำ OOP จริงหรือใช้ภาษาที่เหมาะสมกับกระบวนทัศน์ของคุณ


ในตัวอย่างของคุณจะดีกว่าหรือไม่ที่จะใช้ฟังก์ชันฟรี
Ela782

2
@ Ela782 หากภาษามีฟังก์ชั่นฟรีให้ใช้

โอเคขอบคุณสำหรับความมั่นใจ ฉันเพิ่งเรียนรู้แนวทางปฏิบัติที่ดีที่สุดนี้เมื่อเร็ว ๆ นี้ อย่างไรก็ตามตอนนี้ฉันมีปัญหาในการเห็นเมื่อฟังก์ชั่นสมาชิกคงที่สาธารณะอาจมีประโยชน์จริง ๆ สมมติว่าในภาษาเช่น C ++ กรณีใช้งานสำหรับทั้งคู่คือเมื่อฟังก์ชั่นไม่ได้ขึ้นอยู่กับหรือต้องการอินสแตนซ์ของคลาสจากนั้นฟังก์ชั่นที่ว่างเป็นคำแนะนำ บางทีนี่อาจเป็นคำถามใหม่
Ela782

1
@ Ela782 ใช่มันอาจทำให้เป็นคำถามที่ดี สองคะแนนด่วน: ใน C ++ โดยเฉพาะสมาชิกแบบสแตติกมีประโยชน์สำหรับการเขียนโปรแกรมเมตาเทมเพลตเนื่องจากคุณสามารถส่งชนิดเป็นพารามิเตอร์เทมเพลต แต่ไม่ใช่เนมสเปซ โดยทั่วไปฟังก์ชั่นแบบคงที่สามารถใช้เพื่อระบุว่าฟังก์ชั่นอย่างใกล้ชิดเป็นของบางคลาสเมื่อเทียบกับเพียงแค่อยู่ใน namespace (คิดว่าstuff::Thing::Load(...)vs stuff::LoadThing())

2

ฉันใช้พวกเขาเป็นฟังก์ชั่นตัวช่วยสำหรับงานทั่วไปตัวอย่าง:

  • แปลงองศาเป็นเรเดียน (และในทางกลับกัน);
  • การแปลงสตริง
  • แปลงจาก enum เป็นอย่างอื่น (ในโครงการนี้ฉันกำลังทำงานพวกเขาทำหน้าที่เป็นตารางแฮช);

ไฟล์ส่วนใหญ่ของฉันที่ฟังก์ชั่นสแตติกของกลุ่มมี Helper ต่อท้ายซึ่งหมายความว่ามันคือสิ่งที่พวกเขาทำช่วยฉันได้เร็วขึ้น


2

สิ่งที่เป็นวิธีคงที่คือ:

วิธีการแบบคงที่ไม่ต้องการอินสแตนซ์ของคลาสและไม่สามารถเข้าถึงข้อมูลโดยนัย (หรือสิ่งนี้, ตัวเอง, ฉัน, ฯลฯ ) ของอินสแตนซ์ดังกล่าว [ 1 ]

ตัวอย่างของวิธีการแบบคงที่มีประโยชน์เมื่อ:

  • วิธีการทั่วโลก / ผู้ช่วย
  • รับผลลัพธ์แบบสอบถามจากคลาส Data Model (การเรียก SP)

เพียงใช้พวกเขาตามความเหมาะสมเท่านั้น

  1. หากคุณพบว่าตัวเองกำลังคัดลอกวิธีการเดียวกันในหลาย ๆ วัตถุให้พิจารณาทำให้วิธีนี้คงที่เพื่อให้คุณสามารถติดตาม DRY
  2. ใช้วิธีการคงที่หากคุณไม่ต้องการอินสแตนซ์ของวัตถุ (คุณไม่ได้ทำงานและตัวแปรอินสแตนซ์ของวัตถุ)

หากข้อมูลจำนวนมากของคุณอยู่นอกวัตถุและพวกเขากำลังทำงานบนวิธีการคงที่แล้วรหัสของคุณไม่ได้มุ่งเน้นวัตถุและอาจเป็นเรื่องยากที่จะรักษา


1

ในความเป็นจริงและเป็นส่วนตัว orthogonal: วิธีการคงที่หรือส่วนตัวหรือไม่หรือทั้งสองอย่าง

คงที่และไม่คงที่ (aka 'วิธีการอินสแตนซ์') บ่งชี้ว่าวิธีการดำเนินงานในชั้นเรียนของตัวเอง (คงที่) หรือในกรณีหนึ่งอย่างใดอย่างหนึ่ง (ไม่คงที่) ขึ้นอยู่กับภาษาคุณสามารถเรียกใช้วิธีการคงที่ผ่านอินสแตนซ์ แต่คุณไม่สามารถเข้าถึงอินสแตนซ์ผ่านวิธีคงที่ (ซึ่งก็หมายความว่าคุณไม่สามารถเรียกวิธีการไม่คงที่จากภายในวิธีการคงที่เพียงเพราะคุณไม่มีthisวัตถุ). ใช้วิธีการแบบคงที่เพื่อใช้พฤติกรรมที่เชื่อมโยงกับแนวคิดในชั้นเรียน แต่ไม่ 'ผูก' กับอินสแตนซ์หนึ่งโดยเฉพาะ สถานการณ์อื่นที่คุณอาจต้องการใช้วิธีการคงที่คือเมื่อคุณมีฟังก์ชั่นที่ทำงานกับสองอินสแตนซ์ของคลาสและไม่มีตัวถูกดำเนินการใดที่สมควรได้รับสถานะพิเศษ - ตัวอย่างเช่นสมมติว่าคุณมีคลาสVectorและคุณต้องการใช้การเพิ่ม; วิธีการเพิ่มของคุณอาจเรียกได้ว่าเป็นa.Add(b)แต่Vector.Add(a, b)อาจเหมาะสมกว่า

ส่วนตัวกับสาธารณะเป็นเรื่องเกี่ยวกับการมองเห็นของวิธี วิธีการส่วนตัวสามารถเข้าถึงได้จากภายในขอบเขตของชั้นเรียนเท่านั้นในขณะที่วิธีสาธารณะสามารถเข้าถึงได้จากทุกที่ การใช้งานที่สำคัญที่สุดสำหรับสิ่งนี้คือการห่อหุ้ม: โดยการทำให้วิธีการเหล่านั้นและคุณสมบัติสาธารณะเป็นที่ต้องการอย่างยิ่งโดยส่วนที่เหลือของรหัสเพื่อสื่อสารกับชั้นเรียนของคุณคุณ จำกัด จุดที่รหัสภายนอกสามารถแนะนำปัญหาและป้องกันปัญหาภายใน ชั้นเรียนของคุณจากการตกเลือดในโครงการที่เหลือ

ดังนั้นกฎของหัวแม่มือ:

  • ทำให้ฟังก์ชั่นสมาชิกทั้งหมดเป็นส่วนตัวยกเว้นสิ่งที่จำเป็นต้องเรียกจากนอกห้องเรียน
  • ทำให้ทุกตัวอย่างวิธีการวิธีการเว้นแต่พวกเขาทำให้รู้สึกถึงแม้ว่าไม่มีอินสแตนซ์ของชั้นเรียนอยู่

0

ฉันใช้วิธีการแบบคงที่ทั้ง C ++ และ C # สำหรับยูทิลิตี้คลาสคลาสที่ไม่มีข้อมูลอินสแตนซ์เพียงหนึ่งวิธีในการรวมกลุ่มของวิธีการที่มีประโยชน์และเกี่ยวข้อง

int count1 = DBUtil::GetCountOfSlackerEmployees();
int count2 = DBUtil::GetCountOfEmployedSlackers();

0

สมมติว่าคุณกำลังพูดถึง C ++ (คุณไม่ได้พูด) และคุณมีข้อกำหนด (เช่นไม่ได้หมายถึงฟังก์ชั่น / วิธีการของสมาชิก):

แม้แต่ฟังก์ชั่นสมาชิกส่วนตัวยังต้องประกาศในส่วนหัวซึ่งหมายความว่ามันจะกลายเป็นส่วนหนึ่งของ API และ ABI ของคลาสแม้ว่าผู้ใช้จะไม่สามารถเรียกมันได้ หากคุณเพิ่มแก้ไขหรือลบฟังก์ชั่นสมาชิกส่วนตัวคุณกำลังบังคับให้คอมไพล์ใหม่ของคลาสที่ต้องพึ่งพาทั้งหมด (ส่วนหัวมีการเปลี่ยนแปลงทำให้ไม่สามารถรู้ได้ดีขึ้น) และเมื่อคุณทำเช่นนั้นในไลบรารีคุณจะต้องพิจารณาความเข้ากันได้ มัน.

ในอีกทางหนึ่งฟังก์ชั่นแบบคงที่ที่กำหนดขอบเขตไฟล์จะไม่ได้รับสัญลักษณ์สาธารณะดังนั้นคุณสามารถเพิ่มแก้ไขหรือลบออกได้ตามที่คุณต้องการและจะไม่มีผลใด ๆ



0

ฟังก์ชั่นคงที่ (และมีความหมายที่แตกต่างกันสำหรับคำนั้นในภาษาต่าง ๆ ) ไม่จำเป็นต้องมีสถานะใด ๆ ที่ถูกเก็บไว้ระหว่างการโทร ถ้ามันเชื่อมโยงกับแนวคิดอย่างใกล้ชิดกับสิ่งที่คลาสทำให้เป็นฟังก์ชันคลาส (เช่นเดียวกับในคลาสที่ไม่ใช่วัตถุ) หรือถ้าไม่ใช่ให้สร้างฟังก์ชันโกลบอล (หรือโมดูลระดับสิ่งใดก็ได้) มันไม่ได้อยู่ในวัตถุถ้ามันไม่จำเป็นต้องมีสถานะของวัตถุ

หากคุณส่งผ่านสถานะตลอดเวลาไม่ใช่ฟังก์ชันไร้สัญชาติจริงๆคุณเพียงแค่สร้างฟังก์ชัน stateful ด้วยไวยากรณ์ไร้สัญชาติ ในกรณีนั้นอาจเป็นของวัตถุที่เรียกหรืออาจเป็น refactoring เพื่อปรับสถานะและพฤติกรรมให้ดีขึ้น


0

"ทำไมไม่เพียงแทนที่ฟังก์ชั่นสมาชิกส่วนตัวทั้งหมดด้วยฟังก์ชั่นสแตติกแทน"

... เนื่องจากสมาชิกส่วนตัวสามารถเข้าถึงข้อมูลอินสแตนซ์ในขณะที่อนุญาตให้เกิดขึ้นจากการโทรที่ทำในฟังก์ชั่นสมาชิกคนอื่นเท่านั้น ฟังก์ชั่นสแตติกสามารถเป็นส่วนตัว แต่จะไม่สามารถที่จะแก้ไขหรืออ้างถึงอินสแตนซ์ของชั้นเรียนเว้นแต่ว่าอินสแตนซ์จะถูกส่งผ่านเป็นพารามิเตอร์


0

เป็นเรื่องตลกที่ไม่มีใครสามารถให้คำตอบที่ดีได้ ฉันไม่แน่ใจว่าอันนี้ก็เหมือนกัน คุณอาจใช้มันเป็นคำใบ้ว่าควรใช้ให้น้อยที่สุด พวกเขาอยู่หลังจากขั้นตอนทั้งหมดมากกว่า OOP

นี่คือตัวอย่างเพิ่มเติม:

ใน Obj-C ที่พวกเขาเรียกว่าวิธีการเรียนพวกเขามักจะใช้เป็น wrappers การจัดสรรที่วัตถุจะใส่ในสระว่ายน้ำนับอ้างอิงก่อนที่จะถูกส่งกลับ

อีกตัวอย่างจาก Obj-C คือการลงทะเบียนคลาสใหม่ในคลาสคอลเลกชัน สมมติว่าคุณมีชุดของคลาสที่จัดการแต่ละไฟล์ชนิดหนึ่ง เมื่อคุณสร้างคลาสใหม่สำหรับประเภทไฟล์ใหม่คุณสามารถลงทะเบียนในคอลเลกชัน (ตัวแปรทั่วโลก) โดยใช้วิธีการคงที่ในชั้นเรียนที่กำหนดประเภทของไฟล์

ใน C ++ การใช้อื่นที่ฉันสามารถคิดได้คือการจับข้อผิดพลาดเบา ๆ ฟังก์ชันตัวสร้างของคุณไม่สามารถล้มเหลวยกเว้นโดยการโยนข้อยกเว้น คุณสามารถตั้งค่าตัวแปรอินสแตนซ์ข้อผิดพลาดได้ แต่ก็ไม่เหมาะสมเสมอไป แต่คุณสามารถทำส่วนต่าง ๆ ที่อาจล้มเหลวใน wrapper แบบคงที่แล้วจัดสรรและส่งคืนวัตถุใหม่หรือ NULL เมื่อเกิดความล้มเหลว


0

สมมติว่าคุณต้องการคำนวณไซนัสของบางสิ่ง

ไม่คงที่:

Math math = new Math()
double y = math.sin(x)

ด้วยคงที่:

double y = Math.sin(x)

มันไม่มีเหตุผลที่จะทำให้sinไม่คงที่ มันไร้สัญชาติและเพียงแค่ประมวลผลอินพุต

ฟังก์ชั่นคงที่ไม่ได้ผูกติดอยู่กับวัตถุเฉพาะ เป็นฟังก์ชัน "ทั่วไป" ที่ไม่ขึ้นกับสถานะภายในของวัตถุ


วิธีการคงที่ไม่ได้ "รับประกันว่าจะไร้สัญชาติ" แม้ว่าจะเป็นความจริงที่ว่าพวกเขาไม่สามารถใช้ข้อมูลอินสแตนซ์ได้ แต่พวกเขาก็สามารถเข้าถึงบางสถานะ (เช่นสมาชิกแบบสแตติกทั้งคลาสที่เมธอดสแตติกเป็นของและรัฐอื่นทั่วโลกที่มองเห็นได้เช่นตัวแปรคงที่ของคลาสอื่น ๆ )

@delnan: จริง ... คุณพูดถูก ขอผมแก้ไขตอนนี้
dagnelies

ไม่คงที่: x.sin(). คำตอบของคุณสมมติว่าบาปควรเป็นหน้าที่ของ "คณิตศาสตร์" ในขณะที่มันทำงานได้อย่างชัดเจนในสองครั้ง
AjahnCharles

0

สายที่นี่ แต่ฉันต้องการที่จะพยายามสร้างคำนิยามที่แม่นยำ: ฟังก์ชั่นคงที่เป็นฟังก์ชั่นที่ไม่ได้หรือไม่สามารถอ้างอิงคุณสมบัติ / วิธีการอินสแตนซ์ของชั้นเรียนที่มี

ในบางภาษาเช่น C # อาจมีสแตติกฟิลด์หรือคุณสมบัติในคลาสสแตติกดังนั้นจึงไม่ถูกต้องที่จะบอกว่าพวกเขาไม่ได้ใช้สำหรับสถานะ ฟังก์ชั่นคงอาจใช้ประโยชน์จากสถานะคงที่ (ทั่วโลก)

โดยทั่วไปมันจะเดือดลงไปที่: ฟังก์ชั่นคงที่เช่นเดียวกับสิ่งคงที่มีประโยชน์เมื่อมันทำให้รู้สึกว่าพวกเขาจะสามารถใช้ได้เสมอโดยไม่ต้องพึ่งพาอินสแตนซ์ที่ไม่คงที่

ฟังก์ชันตัวช่วยเช่นฟังก์ชั่นคณิตศาสตร์เป็นตัวอย่างที่มีประโยชน์

หากคลาสที่คุณสร้างต้องการให้ข้อมูลไม่เปลี่ยนรูปแบบมันอาจสมเหตุสมผลในการสร้างฟังก์ชั่นสแตติกที่รับอินสแตนซ์และส่งผ่านอินสแตนซ์ใหม่เนื่องจากอินสแตนซ์ไม่สามารถเปลี่ยนได้ (หรือไม่ควร) ตัวอย่างเช่นคลาสสตริอาจมีฟังก์ชั่นคงที่ที่ใช้ในสตริง (หรือ 2 หรือมากกว่า) และส่งกลับสตริงใหม่

อีกเหตุผลหนึ่งอาจเป็นเพราะมีคลาสที่เก็บสถานะโลกหรือข้อมูลบางชนิด อาจมีฟังก์ชั่นสแตติกที่ทำงานกับคุณสมบัติสแตติกหรือฟิลด์ในคลาสสแตติกนั้น


0

ฉันต้องการชี้ให้เห็นการใช้งานแบบคงที่ f () อีกครั้ง

http://www.parashift.com/c++-faq/named-ctor-idiom.html

ทำสิ่งต่อไปนี้: staticฟังก์ชั่นช่วยให้คุณสร้าง "Named Constructors" เช่นคุณตั้งชื่อฟังก์ชั่นสแตติกของคุณด้วยชื่อที่เหมาะสมและการจัดทำเอกสารด้วยตนเองและฟังก์ชั่นแบบคงที่นี้เรียกหนึ่งในคอนสตรัคชั่น มันยากที่จะแยกแยะระหว่างพวกเขา)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.