ฟังก์ชั่น "คงที่" ใน C คืออะไร?


506

คำถามเกี่ยวกับธรรมดา ฟังก์ชั่นไม่ static วิธีการดังที่อธิบายไว้ในความคิดเห็น

ฉันเข้าใจว่าstaticตัวแปรคืออะไร แต่staticฟังก์ชั่นคืออะไร?

และทำไมถ้าฉันประกาศฟังก์ชั่นสมมุติvoid print_matrixว่าa.c(โดยไม่มีa.h) และรวม"a.c"- ฉันจะได้รับ"print_matrix@@....) already defined in a.obj"แต่ถ้าฉันประกาศเมื่อstatic void print_matrixมันรวบรวมมัน?

อัปเดตเพียงเพื่อล้างสิ่งต่าง ๆ - ฉันรู้ว่าการรวมกัน.cนั้นไม่ดีเท่าที่คุณหลายคนชี้ให้เห็น ฉันเพียงแค่ทำมันไปยังพื้นที่ที่ชัดเจนชั่วคราวmain.cจนกว่าฉันจะมีความคิดที่ดีของวิธีการทุกกลุ่มฟังก์ชั่นที่เป็นที่เหมาะสม.hและ.cไฟล์ เป็นการแก้ปัญหาชั่วคราวที่รวดเร็ว

คำตอบ:


685

staticฟังก์ชั่นเป็นฟังก์ชั่นที่มองเห็นได้เฉพาะฟังก์ชั่นอื่น ๆ ในไฟล์เดียวกัน (แม่นยำยิ่งขึ้นหน่วยการแปลเดียวกัน )

แก้ไข : สำหรับผู้ที่คิดว่าผู้เขียนคำถามหมายถึง 'วิธีการเรียน': เมื่อติดแท็กคำถามCเขาหมายถึงฟังก์ชั่น C แบบธรรมดา สำหรับเมธอดคลาส (C ++ / Java / ... ) staticหมายความว่าสามารถเรียกเมธอดนี้บนคลาสเองโดยไม่จำเป็นต้องมีอินสแตนซ์ของคลาสนั้น


2
ที่จริงฉันไม่ได้ติดแท็ก c ++ ผู้ดูแลระบบบางคนอาจทำ แต่มันเกี่ยวกับ C ++ ดังนั้น C ++ แตกต่างกันอย่างไร
Slava V

16
วิธีการ C ++ มักจะถูกเรียกว่า "ฟังก์ชั่นสมาชิก" ดังนั้นฉันยอมรับว่า C ++ แนะนำความคลุมเครือเล็กน้อย ไม่ใช่ความผิดของคุณ - ภาษาใช้คำสำคัญสำหรับสองสิ่งที่แตกต่างกัน
Chuck

2
ไม่เขายังคงหมายถึงฟังก์ชั่น C ++ ฟังก์ชันฟรี C ++ แทนที่จะเป็นฟังก์ชันสมาชิก C ++
การแข่งขัน Lightness ใน Orbit

3
@Chuck: คำศัพท์ C ++ ไม่เคยใช้คำว่า "method"; นั่นคือคำศัพท์ Java - ในเอกสารมาตรฐาน C ++ มันมักจะเรียกว่า "ฟังก์ชั่นสมาชิก" (ดูคำตอบนี้หรือคำศัพท์นี้ของคำศัพท์ C ++ vs Java (เช่น C ++ ใช้ "ข้อมูลสมาชิก" และ Java ใช้ "ฟิลด์" ฯลฯ ))
ShreevatsaR

6
เพื่อชี้แจงคำตอบนี้เล็กน้อย: ชื่อของฟังก์ชั่นสามารถมองเห็นได้เฉพาะส่วนอื่น ๆ ของหน่วยการแปลเดียวกันด้านล่างการประกาศครั้งแรกของชื่อนั้น ฟังก์ชั่นอาจถูกเรียกจากหน่วยอื่น ๆ (และส่วนก่อนหน้าของหน่วยเดียวกัน) ด้วยวิธีการอื่นเช่นตัวชี้ฟังก์ชั่น
MM

199

มีความแตกต่างใหญ่ระหว่างฟังก์ชั่นคงที่ใน C และฟังก์ชั่นสมาชิกคงที่ใน C ++ ใน C ฟังก์ชั่นคงที่ไม่สามารถมองเห็นได้นอกหน่วยแปลซึ่งเป็นไฟล์วัตถุที่รวบรวมไว้ กล่าวอีกนัยหนึ่งการทำให้ฟังก์ชั่นคงที่ จำกัด ขอบเขตของมัน คุณสามารถคิดว่าฟังก์ชั่นแบบคงที่เป็น "ส่วนตัว" กับไฟล์ * .c (แม้ว่าจะไม่ถูกต้องอย่างเคร่งครัด)

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

ฟังก์ชั่นสมาชิกไม่คงที่สามารถเข้าถึงข้อมูลสมาชิกทั้งหมดของระดับ: คงที่และไม่คงที่ ฟังก์ชันสมาชิกแบบคงที่สามารถทำงานกับสมาชิกข้อมูลแบบคงที่เท่านั้น

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


42
C ++ มีไฟล์คงที่เช่นกัน ไม่จำเป็นต้องนำ C เข้ามาในส่วนนี้
การแข่งขัน Lightness ใน Orbit

17
ใน C ++ ฟังก์ชันสแตติกเป็นฟังก์ชันสแตติก ฟังก์ชั่นสมาชิกคงที่เป็นฟังก์ชั่นสมาชิกคงที่หรือที่เรียกว่าวิธีการ ความจริงที่ว่า C ไม่มีสมาชิกไม่ได้หมายความว่าฟังก์ชั่นคือ "C"
Gerasimos R

3
มีความแตกต่างระหว่าง global var และ class static var (ยกเว้น namespace) หรือไม่?
Alexander Malakhov

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

2
มีคนอธิบายได้ไหมว่าทำไมการคิดว่าฟังก์ชั่นสแตติกเป็นส่วนตัวกับไฟล์. c นั้นไม่ถูกต้องอย่างเคร่งครัด มีอะไรให้พูดอีกเหรอ?
YoTengoUnLCD

77

มีการใช้สองครั้งสำหรับคำหลักคงที่เมื่อมันมาถึงฟังก์ชั่นใน C ++

ประการแรกคือการทำเครื่องหมายฟังก์ชั่นว่ามีการเชื่อมโยงภายในจึงไม่สามารถอ้างอิงในหน่วยการแปลอื่น ๆ การใช้งานนี้เลิกใช้แล้วใน C ++ แนะนำให้ใช้เนมสเปซที่ไม่มีชื่อสำหรับการใช้งานนี้

// inside some .cpp file:

static void foo();    // old "C" way of having internal linkage

// C++ way:
namespace
{
   void this_function_has_internal_linkage()
   {
      // ...
   }
}

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


1
คำถามเป็นเรื่องเกี่ยวกับคงที่ในค
Deqing

8
@Deqing คำถามถูกติดแท็ก C ++ และผู้เขียนพูดถึงการใช้ไฟล์ ".cpp"
Brian Neal

57

ตัวอย่างขอบเขตหลายไฟล์ที่รันได้น้อยที่สุด

ที่นี่ฉันแสดงให้เห็นว่าstaticมีผลกระทบต่อขอบเขตของคำนิยามฟังก์ชั่นในหลายไฟล์

ไฟฟ้ากระแสสลับ

#include <stdio.h>

/* Undefined behavior: already defined in main.
 * Binutils 2.24 gives an error and refuses to link.
 * /programming/27667277/why-does-borland-compile-with-multiple-definitions-of-same-object-in-different-c
 */
/*void f() { puts("a f"); }*/

/* OK: only declared, not defined. Will use the one in main. */
void f(void);

/* OK: only visible to this file. */
static void sf() { puts("a sf"); }

void a() {
    f();
    sf();
}

main.c

#include <stdio.h>

void a(void);        

void f() { puts("main f"); }

static void sf() { puts("main sf"); }

void m() {
    f();
    sf();
}

int main() {
    m();
    a();
    return 0;
}

GitHub ต้นน้ำ

รวบรวมและเรียกใช้:

gcc -c a.c -o a.o
gcc -c main.c -o main.o
gcc -o main main.o a.o
./main

เอาท์พุท:

main f
main sf
main f
a sf

การตีความ

  • มีฟังก์ชั่นแยกกันสองฟังก์ชั่นsfหนึ่งสำหรับแต่ละไฟล์
  • มีฟังก์ชั่นที่ใช้ร่วมกันเดียว f

ตามปกติขอบเขตที่เล็กลงจะดีกว่าดังนั้นจะประกาศฟังก์ชั่นเสมอstaticถ้าทำได้

ในการเขียนโปรแกรม C ไฟล์มักจะใช้เพื่อแสดง "คลาส" และstaticฟังก์ชั่นแสดงวิธีการ "ส่วนตัว" ของชั้นเรียน

รูปแบบ C ทั่วไปคือการส่งผ่านthisstruct รอบ ๆ เป็นอาร์กิวเมนต์ "วิธี" แรกซึ่งเป็นสิ่ง C + + ทำภายใต้ประทุน

มาตรฐานพูดถึงอะไร

C99 N1256 ฉบับร่าง 6.7.1 "ตัวระบุคลาสหน่วยเก็บข้อมูล" ระบุว่าstaticเป็น "ตัวระบุระดับชั้นเก็บข้อมูล"

6.2.2 / 3 "การเชื่อมโยงของตัวระบุ" กล่าวstaticถึงนัยinternal linkage:

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

และ 6.2.2 / 2 บอกว่ามันinternal linkageมีพฤติกรรมเหมือนในตัวอย่างของเรา:

ในชุดของหน่วยการแปลและไลบรารีที่ประกอบด้วยโปรแกรมทั้งหมดการประกาศของตัวระบุเฉพาะที่มีการเชื่อมโยงภายนอกจะแสดงวัตถุหรือฟังก์ชันเดียวกัน ภายในหนึ่งหน่วยการแปลการประกาศของตัวระบุแต่ละตัวที่มีการเชื่อมโยงภายในหมายถึงวัตถุหรือฟังก์ชันเดียวกัน

โดยที่ "หน่วยการแปล" เป็นไฟล์ต้นฉบับหลังจากประมวลผลล่วงหน้า

GCC ใช้สำหรับ ELF (Linux) ได้อย่างไร

ด้วยการSTB_LOCALผูกมัด

ถ้าเรารวบรวม:

int f() { return 0; }
static int sf() { return 0; }

และแยกตารางสัญลักษณ์ด้วย:

readelf -s main.o

ผลลัพธ์ประกอบด้วย:

Num:    Value          Size Type    Bind   Vis      Ndx Name
  5: 000000000000000b    11 FUNC    LOCAL  DEFAULT    1 sf
  9: 0000000000000000    11 FUNC    GLOBAL DEFAULT    1 f

ดังนั้นการผูกเป็นความแตกต่างที่สำคัญระหว่างพวกเขา Valueเป็นเพียงส่วนชดเชยของพวกเขาใน.bssส่วนดังนั้นเราจึงคาดหวังว่ามันจะแตกต่างกัน

STB_LOCALเป็นเอกสารเกี่ยวกับข้อมูลจำเพาะของเอลฟ์ที่http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html :

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

staticซึ่งจะทำให้มันเป็นทางเลือกที่สมบูรณ์แบบที่จะเป็นตัวแทน

ฟังก์ชั่นที่ไม่มีสถิตคือSTB_GLOBALและ spec บอกว่า:

เมื่อตัวแก้ไขลิงก์รวมหลายอ็อบเจ็กต์ไฟล์ที่เปลี่ยนตำแหน่งได้มันไม่อนุญาตให้นิยามหลาย ๆ สัญลักษณ์ STB_GLOBAL ด้วยชื่อเดียวกัน

ซึ่งเชื่อมโยงกับข้อผิดพลาดการเชื่อมโยงในหลาย ๆ คำจำกัดความคงที่

ถ้าเราเหวี่ยงขึ้นการเพิ่มประสิทธิภาพด้วย-O3การsfสัญลักษณ์จะถูกลบออกทั้งหมดจากตารางสัญลักษณ์: มันไม่สามารถนำมาใช้จากนอกนะ สิ่งที่ต้องทำทำไมให้ฟังก์ชั่นคงที่ในตารางสัญลักษณ์เลยเมื่อไม่มีการเพิ่มประสิทธิภาพ? พวกเขาสามารถใช้เพื่ออะไร

ดูสิ่งนี้ด้วย

เนมสเปซที่ไม่ระบุชื่อ C ++

ใน C ++ คุณอาจต้องการใช้เนมสเปซที่ไม่ระบุชื่อแทนสแตติกซึ่งให้ผลที่คล้ายกัน แต่ซ่อนนิยามของประเภทเพิ่มเติม: เนมสเปซที่ไม่มีชื่อ / ไม่ระบุชื่อกับฟังก์ชั่นคงที่


3
หมายเหตุ: void f() { puts("sf"); }(เช่นสองคำจำกัดความของf()) ทำให้เกิดพฤติกรรมที่ไม่ได้กำหนดโดยไม่จำเป็นต้องมีการวินิจฉัย มันเป็นปัญหาเรื่องคุณภาพของลิงค์ลิงเกอร์เพื่อดูข้อความแสดงข้อผิดพลาด
MM

2
นี่คือคำอธิบายที่ดีที่สุดและแม่นยำ! กว่าที่คุณ!
อควา

20

ต่อไปนี้เป็นฟังก์ชั่นเกี่ยวกับ C ธรรมดา - ในคลาส C ++ ตัวดัดแปลง 'static' มีความหมายอื่น

หากคุณมีเพียงไฟล์เดียวโมดิฟายเออร์นี้ไม่สร้างความแตกต่างอย่างแน่นอน ความแตกต่างเกิดขึ้นในโครงการขนาดใหญ่ที่มีหลายไฟล์:

ใน C ทุก ๆ "โมดูล" (การรวมกันของ sample.c และ sample.h) ถูกคอมไพล์อย่างอิสระและหลังจากนั้นไฟล์ออบเจ็กต์ที่รวบรวม (sample.o) ทุกไฟล์จะถูกเชื่อมโยงเข้าด้วยกันเป็นไฟล์เรียกทำงานโดย linker

สมมติว่าคุณมีไฟล์หลายไฟล์ที่คุณรวมไว้ในไฟล์หลักของคุณและสองไฟล์นั้นมีฟังก์ชั่นที่ใช้ภายในเพื่อความสะดวกเท่านั้นที่เรียกว่าadd(int a, b)- คอมไพเลอร์จะสร้างไฟล์วัตถุสำหรับสองโมดูลเหล่านั้นได้อย่างง่ายดาย พบสองฟังก์ชั่นที่มีชื่อเหมือนกันและไม่ทราบว่าควรใช้ฟังก์ชันใด (แม้ว่าจะไม่มีอะไรให้เชื่อมโยงเพราะมันไม่ได้ใช้ที่อื่น แต่อยู่ในไฟล์ของตัวเอง)

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


16

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

ประการที่สอง:

C ++ มีคำศัพท์ที่สับสนบางอย่างที่นี่ - ฉันไม่รู้เกี่ยวกับมันจนกระทั่งชี้ให้เห็นในความคิดเห็น

a) static functions- สืบทอดมาจาก C และสิ่งที่คุณกำลังพูดถึงที่นี่ นอกชั้นเรียนใด ๆ ฟังก์ชั่นคงที่หมายความว่าไม่สามารถมองเห็นได้ภายนอกหน่วยรวบรวมปัจจุบันดังนั้นในกรณีของคุณ a.obj มีสำเนาและรหัสอื่นของคุณมีสำเนาอิสระ (bloating ปฏิบัติการขั้นสุดท้ายที่มีหลายสำเนาของรหัส)

ข) static member function- สิ่งที่คำวัตถุปฐมนิเทศคงวิธีการ อาศัยอยู่ในชั้นเรียน คุณเรียกสิ่งนี้กับคลาสแทนผ่านอินสแตนซ์ของวัตถุ

นิยามฟังก์ชันแบบสแตติกทั้งสองนี้แตกต่างกันอย่างสิ้นเชิง ระวัง - นี่คือมังกร


ฉันทำเพื่อล้างพื้นที่บางส่วนใน main.cpp จนกว่าฉันจะตัดสินใจว่าจะจัดระเบียบไฟล์ในไลบรารีพร้อมกับ. hpp ที่เหมาะสมได้อย่างไร มีความคิดที่ดีกว่าวิธีการทำเช่นนี้?
Slava V

1
คำศัพท์ที่ถูกต้องใน C ++ คือฟังก์ชั่นสมาชิกไม่ใช่วิธีการ ไม่มี "วิธี" ในภาษา C ++ เมธอดเป็นคำศัพท์ OO ทั่วไป C ++ ดำเนินการผ่านฟังก์ชั่นสมาชิก
Brian Neal

14

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


7

ฟังก์ชั่นคงที่เป็นสิ่งหนึ่งที่สามารถเรียกใช้ในชั้นเรียนของตัวเองซึ่งตรงข้ามกับตัวอย่างของชั้นเรียน

ตัวอย่างเช่น non-static จะเป็น:

Person* tom = new Person();
tom->setName("Tom");

วิธีนี้ใช้ได้กับอินสแตนซ์ของคลาสไม่ใช่คลาสเอง อย่างไรก็ตามคุณสามารถมีวิธีการคงที่ที่สามารถทำงานได้โดยไม่ต้องมีอินสแตนซ์ บางครั้งใช้ในรูปแบบ Factory:

Person* tom = Person::createNewPerson();

2
ฉันว่าคุณกำลังพูดถึง "วิธีการ" คงที่ไม่ใช่ฟังก์ชั่น
Slava V

ฉันคิดว่าคุณหมายถึงฟังก์ชั่นคงที่ภายในชั้นเรียน
นกแก้ว

ถ้าฉันรู้จัก "เมธอด" เรียกว่า "เมธอดฟังก์ชั่น" ใน C ++ ฉันก็จะมีความชัดเจนมากขึ้น ดีตอนนี้ฉันทำ :) ขอบคุณต่อไป
Slava V

5
ไม่มี "วิธีการ" ใน C ++ เพียงฟังก์ชั่น มาตรฐาน C ++ ไม่ได้พูดถึง "วิธีการ" เพียงแค่ "ฟังก์ชั่น"
Brian Neal

1
@Puddle ฉันรู้ว่าคุณกำลังพูดอะไร แต่ในมาตรฐาน C ++ ไม่มีคำจำกัดความของ "method" C ++ มีฟังก์ชันหลากหลายชนิดเท่านั้น "วิธีการ" เป็นคำศัพท์ OO ทั่วไปและใช้ในภาษาอื่นและไม่เป็นทางการใน C ++ วิธีการที่รู้จักกันอย่างเป็นทางการว่า "ฟังก์ชั่นสมาชิก" ใน C ++
Brian Neal

7

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

มาตรฐานอาจพูดว่า:

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

นั่นคือวิธี C ในการดูฟังก์ชั่นแบบคงที่ สิ่งนี้เลิกใช้แล้วใน C ++

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

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


7

คำตอบของฟังก์ชั่นคงที่ขึ้นอยู่กับภาษา:

1) ในภาษาที่ไม่มี OOPS เช่น C หมายความว่าฟังก์ชั่นสามารถเข้าถึงได้เฉพาะภายในไฟล์ที่มีการกำหนดไว้เท่านั้น

2) ในภาษาที่มี OOPS เช่น C ++ หมายความว่าฟังก์ชั่นสามารถเรียกใช้โดยตรงบนคลาสโดยไม่ต้องสร้างอินสแตนซ์ของมัน


นี่ไม่เป็นความจริง. คำอธิบายของย่อหน้าที่สองของคุณอ้างถึง " ฟังก์ชั่นสมาชิกคงที่ " ของชั้นเรียนไม่ใช่ " ฟังก์ชั่นคงที่ " ใน C ++ ฟังก์ชั่นที่ผ่านการรับรองstaticมีขอบเขตไฟล์เหมือนใน C
RobertS รองรับ Monica Cellio

0

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

นี่คือตัวอย่างง่ายๆ

main.c

#include <stdio.h>

static void test() 
{
    ghost(); // This is an unexist function.
}

int main()
{
    int ret = 0;

#ifdef TEST
#else
    test();
#endif
    return (ret);
} 

และคอมไพล์ด้วย

gcc -o main main.c

คุณจะเห็นมันล้มเหลว เพราะคุณยังไม่ได้ใช้ฟังก์ชั่น ghost ()

แต่ถ้าเราใช้คำสั่งต่อไปนี้

gcc -DTEST -O2 -o main main.c

มันประสบความสำเร็จและโปรแกรมนี้สามารถดำเนินการได้ตามปกติ

ทำไม? มี 3 ประเด็นสำคัญคือ

  1. -O2: ระดับการปรับให้เหมาะสมของคอมไพเลอร์อย่างน้อย 2
  2. -DTEST: กำหนดการทดสอบดังนั้น test () จะไม่ถูกเรียก
  3. กำหนด "คงที่" เพื่อทดสอบ ()

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


0

" เป็นอะไร ‘ staticฟังก์ชั่น’ ใน C? "

เริ่มกันที่จุดเริ่มต้นกันดีกว่า

มันขึ้นอยู่กับสิ่งที่เรียกว่า "การเชื่อมโยง":

" ตัวระบุที่ประกาศในขอบเขตที่แตกต่างกันหรืออยู่ในขอบเขตเดียวกันมากกว่าหนึ่งครั้งสามารถอ้างถึงวัตถุหรือฟังก์ชั่นเดียวกันโดยกระบวนการที่เรียกว่าการเชื่อมโยง 29) การเชื่อมโยงมีสามประเภท: ภายนอกภายในและไม่มีเลย "

ที่มา: C18, 6.2.2 / 1


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

ที่มา: C18, 6.2.2 / 2


ถ้าฟังก์ชั่นถูกกำหนดโดยไม่มีตัวระบุคลาสหน่วยเก็บข้อมูล, ฟังก์ชั่นมีการexternเชื่อมโยงอัลตามค่าเริ่มต้น:

"ถ้าประกาศระบุสำหรับฟังก์ชั่นที่ใช้งานไม่ได้มีระบุการจัดเก็บข้อมูลระดับความเชื่อมโยงมันจะถูกกำหนดว่าเป็นถ้ามันถูกประกาศที่มีการจัดเก็บข้อมูลชั้นระบุextern ."

ที่มา: C18, 6.2.2 / 5

ซึ่งหมายความว่า - หากโปรแกรมของคุณมีหน่วยการแปลหลายไฟล์ / ไฟล์ต้นฉบับ ( .cหรือ.cpp) - ฟังก์ชั่นนี้สามารถมองเห็นได้ในทุกไฟล์ / ไฟล์ต้นฉบับที่โปรแกรมของคุณมี

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

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

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


30) การประกาศฟังก์ชั่นสามารถมีเฉพาะระดับการจัดเก็บข้อมูลเฉพาะถ้ามันอยู่ที่ขอบเขตไฟล์; ดู 6.7.1

ที่มา: C18, 6.2.2 / 3


ดังนั้นstaticฟังก์ชั่นเพียงทำให้รู้สึก iff:

  1. โปรแกรมของคุณมีหน่วยการแปล / ไฟล์ต้นฉบับหลายไฟล์ ( .cหรือ.cpp)

    และ

  2. คุณต้องการ จำกัด ขอบเขตของฟังก์ชันให้กับไฟล์ซึ่งมีการกำหนดฟังก์ชันเฉพาะไว้

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


หมายเหตุด้านข้าง:

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