Hàm tĩnh tĩnh trong C là gì?


506

Câu hỏi là về đồng bằng chức năng, không static phương pháp, như được làm rõ trong ý kiến.

Tôi hiểu staticbiến là gì, nhưng statichàm là gì?

Và tại sao nếu tôi khai báo một hàm, giả sử void print_matrix, hãy nói a.c(KHÔNG CÓ a.h) và bao gồm "a.c"- Tôi nhận được "print_matrix@@....) already defined in a.obj", NHƯNG nếu tôi khai báo hàm static void print_matrixđó thì nó sẽ biên dịch?

CẬP NHẬT Chỉ để làm sáng tỏ mọi thứ - Tôi biết rằng bao gồm .clà xấu, như nhiều bạn đã chỉ ra. Tôi chỉ làm điều đó để tạm thời xóa không gian main.ccho đến khi tôi có ý tưởng tốt hơn về cách nhóm tất cả các chức năng đó thành các tệp .h.ctệp thích hợp . Chỉ là một giải pháp tạm thời, nhanh chóng.

Câu trả lời:


685

staticcác hàm là các hàm chỉ hiển thị cho các hàm khác trong cùng một tệp (chính xác hơn là cùng một đơn vị dịch ).

EDIT : Đối với những người nghĩ rằng tác giả của các câu hỏi có nghĩa là 'phương thức lớp': Khi câu hỏi được gắn thẻ C, anh ta có nghĩa là một hàm C cũ đơn giản. Đối với các phương thức lớp (C ++ / Java / ...), staticcó nghĩa là phương thức này có thể được gọi trên chính lớp đó, không cần phiên bản của lớp đó.


2
Trên thực tế tôi đã không gắn thẻ c ++, một số quản trị viên có thể đã làm, nhưng đó là về C ++, vậy sự khác biệt trong C ++ là gì?
Slava V

16
Các phương thức C ++ thường được gọi là "các hàm thành viên", vì vậy tôi đồng ý rằng C ++ giới thiệu một chút mơ hồ. Đó không phải là lỗi của bạn - ngôn ngữ chỉ sử dụng từ khóa cho hai thứ khác nhau.
Chuck

2
Không, anh ta vẫn có nghĩa là một chức năng C ++. Hàm C ++ miễn phí thay vì hàm thành viên C ++.
Các cuộc đua nhẹ nhàng trong quỹ đạo

3
@Chuck: Thuật ngữ C ++ không bao giờ sử dụng từ "phương thức"; đó là thuật ngữ Java - trong các tài liệu tiêu chuẩn C ++, nó luôn được gọi là "hàm thành viên" (xem câu trả lời này hoặc bảng chú giải thuật ngữ C ++ so với các thuật ngữ Java (ví dụ: C ++ sử dụng "thành viên dữ liệu" và Java sử dụng "trường", v.v.)).
ShreevatsaR

6
Để làm rõ câu trả lời này một chút: tên của hàm chỉ hiển thị cho các phần khác của cùng một đơn vị dịch, bên dưới khai báo đầu tiên của tên đó. Hàm có thể được gọi từ các đơn vị khác (và các phần trước đó của cùng đơn vị) thông qua các phương tiện khác, ví dụ: con trỏ hàm.
MM

199

Có một sự khác biệt lớn giữa các hàm tĩnh trong C và các hàm thành viên tĩnh trong C ++. Trong C, một hàm tĩnh không thể nhìn thấy bên ngoài đơn vị dịch của nó, đó là tệp đối tượng mà nó được biên dịch thành. Nói cách khác, làm cho một hàm tĩnh giới hạn phạm vi của nó. Bạn có thể nghĩ về một hàm tĩnh là "riêng tư" đối với tệp * .c của nó (mặc dù điều đó không đúng hoàn toàn).

Trong C ++, "tĩnh" cũng có thể áp dụng cho các hàm thành viên và thành viên dữ liệu của các lớp. Một thành viên dữ liệu tĩnh cũng được gọi là "biến lớp", trong khi thành viên dữ liệu không tĩnh là "biến thể hiện". Đây là thuật ngữ của Smalltalk. Điều này có nghĩa là chỉ có một bản sao của một thành viên dữ liệu tĩnh được chia sẻ bởi tất cả các đối tượng của một lớp, trong khi mỗi đối tượng có một bản sao riêng của một thành viên dữ liệu không tĩnh. Vì vậy, một thành viên dữ liệu tĩnh về cơ bản là một biến toàn cục, đó là một thành viên của một lớp.

Các hàm thành viên không tĩnh có thể truy cập tất cả các thành viên dữ liệu của lớp: tĩnh và không tĩnh. Các hàm thành viên tĩnh chỉ có thể hoạt động trên các thành viên dữ liệu tĩnh.

Một cách để nghĩ về điều này là trong C ++, các thành viên dữ liệu tĩnh và các hàm thành viên tĩnh không thuộc về bất kỳ đối tượng nào, mà thuộc về toàn bộ lớp.


42
C ++ cũng có tệp tĩnh. Không cần phải đưa C vào đây.
Các cuộc đua nhẹ nhàng trong quỹ đạo

17
Trong C ++, hàm tĩnh là hàm tĩnh. Hàm thành viên tĩnh là hàm thành viên tĩnh, còn được gọi là phương thức. Việc C không có thành viên không có nghĩa là các hàm là "C".
Gerasimos R

3
Có sự khác biệt nào giữa var toàn cầu và var tĩnh lớp (ngoại trừ không gian tên) không?
Alexander Malakhov

3
Không gian tên là sự khác biệt chính. Sự khác biệt khác là bạn có thể đặt thành viên dữ liệu tĩnh ở chế độ riêng tư và do đó chỉ có thể truy cập được từ bên trong các hàm thành viên của lớp. Nói cách khác, bạn có nhiều quyền kiểm soát hơn đối với một thành viên dữ liệu tĩnh so với biến toàn cục.
Dima

2
Ai đó có thể giải thích tại sao nghĩ về một hàm tĩnh là riêng tư đối với tệp .c của nó không đúng hoàn toàn không? Còn lại gì để nói?
YoTengoUnLCD

77

Có hai cách sử dụng cho từ khóa tĩnh khi nói đến các chức năng trong C ++.

Đầu tiên là đánh dấu chức năng là có liên kết nội bộ để nó không thể được tham chiếu trong các đơn vị dịch thuật khác. Cách sử dụng này không được dùng trong C ++. Không gian tên không tên được ưa thích cho việc sử dụng này.

// inside some .cpp file:

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

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

Việc sử dụng thứ hai là trong bối cảnh của một lớp. Nếu một lớp có chức năng thành viên tĩnh, điều đó có nghĩa là chức năng đó là thành viên của lớp (và có quyền truy cập thông thường đến các thành viên khác), nhưng nó không cần phải được gọi thông qua một đối tượng cụ thể. Nói cách khác, bên trong hàm đó, không có con trỏ "này".


1
Câu hỏi là về tĩnh trong c.
De Khánh

8
@De Khánh câu hỏi ban đầu được gắn thẻ C ++ và tác giả nói về việc sử dụng các tệp ".cpp".
Brian Neal

57

Ví dụ phạm vi đa tệp có thể chạy tối thiểu

Ở đây tôi minh họa cách staticảnh hưởng đến phạm vi định nghĩa hàm trên nhiều tệp.

AC

#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();
}

C chính

#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 ngược dòng .

Biên dịch và chạy:

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

Đầu ra:

main f
main sf
main f
a sf

Diễn dịch

  • Có hai chức năng riêng biệt sf, một chức năng cho mỗi tệp
  • có một chức năng chia sẻ duy nhất f

Như thường lệ, phạm vi càng nhỏ thì càng tốt, vì vậy luôn luôn khai báo các hàm staticnếu bạn có thể.

Trong lập trình C, các tệp thường được sử dụng để đại diện cho "các lớp" và các statichàm đại diện cho các phương thức "riêng tư" của lớp.

Một mẫu C phổ biến là truyền một thiscấu trúc xung quanh làm đối số "phương thức" đầu tiên, về cơ bản là những gì C ++ thực hiện dưới mui xe.

Những tiêu chuẩn nói về nó

C99 N1256 dự thảo 6.7.1 "Trình xác định lớp lưu trữ" nói rằng đó staticlà "trình xác định lớp lưu trữ".

6.2.2 / 3 "Liên kết của định danh" cho biết staticngụ ý internal linkage:

Nếu khai báo của một định danh phạm vi tệp cho một đối tượng hoặc một hàm chứa định danh lớp lưu trữ tĩnh, thì định danh có liên kết bên trong.

và 6.2.2 / 2 nói rằng internal linkagehành xử như trong ví dụ của chúng tôi:

Trong tập hợp các đơn vị dịch thuật và thư viện cấu thành toàn bộ chương trình, mỗi khai báo của một mã định danh cụ thể có liên kết bên ngoài biểu thị cùng một đối tượng hoặc chức năng. Trong một đơn vị dịch thuật, mỗi khai báo của một định danh có liên kết bên trong biểu thị cùng một đối tượng hoặc chức năng.

trong đó "đơn vị dịch" là một tệp nguồn sau khi tiền xử lý.

GCC triển khai nó như thế nào cho ELF (Linux)?

Với sự STB_LOCALràng buộc.

Nếu chúng tôi biên dịch:

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

và tháo rời bảng biểu tượng với:

readelf -s main.o

đầu ra chứa:

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

vì vậy sự ràng buộc là sự khác biệt đáng kể duy nhất giữa chúng. Valuechỉ là phần bù của họ vào .bssphần này, vì vậy chúng tôi hy vọng nó sẽ khác.

STB_LOCALđược ghi lại trên thông số ELF tại http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html :

Các biểu tượng cục bộ không thể nhìn thấy bên ngoài tệp đối tượng chứa định nghĩa của chúng. Các ký hiệu cục bộ cùng tên có thể tồn tại trong nhiều tệp mà không can thiệp lẫn nhau

mà làm cho nó một sự lựa chọn hoàn hảo để đại diện static.

Các chức năng không có tĩnh là STB_GLOBAL, và thông số kỹ thuật nói:

Khi trình soạn thảo liên kết kết hợp một số tệp đối tượng có thể định vị lại, nó không cho phép nhiều định nghĩa của các ký hiệu STB_GLOBAL có cùng tên.

phù hợp với các lỗi liên kết trên nhiều định nghĩa không tĩnh.

Nếu chúng tôi tăng cường tối ưu hóa -O3, sfbiểu tượng sẽ bị xóa hoàn toàn khỏi bảng biểu tượng: không thể sử dụng nó từ bên ngoài. TODO tại sao vẫn giữ các chức năng tĩnh trên bảng biểu tượng khi không có tối ưu hóa? Chúng có thể được sử dụng cho bất cứ điều gì?

Xem thêm

Không gian tên ẩn danh C ++

Trong C ++, bạn có thể muốn sử dụng các không gian tên ẩn danh thay vì tĩnh, điều này đạt được hiệu ứng tương tự, nhưng ẩn thêm các định nghĩa kiểu: Không gian tên ẩn danh / ẩn danh so với các hàm tĩnh


3
lưu ý: void f() { puts("sf"); }(tức là hai định nghĩa về f()) gây ra hành vi không xác định mà không cần chẩn đoán. Đây là một vấn đề chất lượng của liên kết để thực sự thấy một thông báo lỗi.
MM

2
Đây là lời giải thích tốt nhất và chính xác! Hơn bạn!
Aqua

20

Sau đây là về các hàm C đơn giản - trong một lớp C ++, bộ sửa đổi 'static' có nghĩa khác.

Nếu bạn chỉ có một tệp, công cụ sửa đổi này hoàn toàn không có sự khác biệt. Sự khác biệt đến trong các dự án lớn hơn với nhiều tệp:

Trong C, mọi "mô-đun" (sự kết hợp của sample.c và sample.h) được biên dịch độc lập và sau đó mỗi tệp đối tượng được biên dịch (sample.o) được liên kết với nhau thành một tệp thực thi bởi trình liên kết.

Giả sử bạn có một số tệp mà bạn bao gồm trong tệp chính của mình và hai trong số chúng có chức năng chỉ được sử dụng nội bộ để thuận tiện được gọi add(int a, b)- trình biên dịch sẽ dễ dàng tạo tệp đối tượng cho hai mô-đun đó, nhưng trình liên kết sẽ gây ra lỗi, bởi vì trình liên kết sẽ gây ra lỗi, bởi vì nó tìm thấy hai hàm có cùng tên và nó không biết nên sử dụng hàm nào (ngay cả khi không có gì để liên kết, vì chúng không được sử dụng ở nơi nào khác ngoài tệp riêng của nó).

Đây là lý do tại sao bạn thực hiện chức năng này, chỉ được sử dụng nội bộ, một chức năng tĩnh. Trong trường hợp này, trình biên dịch không tạo ra "bạn có thể liên kết thứ này" điển hình cho trình liên kết, để trình liên kết không thấy chức năng này và sẽ không phát sinh lỗi.


16

Đầu tiên: Nói chung là một ý tưởng tồi khi đưa một .cpptệp vào một tệp khác - nó dẫn đến các vấn đề như thế này :-) Cách thông thường là tạo các đơn vị biên dịch riêng biệt và thêm tệp tiêu đề cho tệp được bao gồm.

Thứ hai:

C ++ có một số thuật ngữ khó hiểu ở đây - tôi không biết về nó cho đến khi được chỉ ra trong các bình luận.

a) static functions- được thừa hưởng từ C, và những gì bạn đang nói ở đây. Bên ngoài bất kỳ lớp học. Một tĩnh chức năng phương tiện mà nó không nhìn thấy được bên ngoài đơn vị biên dịch hiện tại - vì vậy trong trường hợp a.obj của bạn có một bản sao và các mã khác của bạn có một bản sao độc lập. (Bồng bềnh thực thi cuối cùng với nhiều bản sao của mã).

b) static member function- những gì Định hướng đối tượng thuật ngữ một phương thức tĩnh . Sống trong một lớp học. Bạn gọi nó với lớp chứ không phải thông qua một thể hiện đối tượng.

Hai định nghĩa hàm tĩnh khác nhau là hoàn toàn khác nhau. Hãy cẩn thận - ở đây là những con rồng.


Chà, tôi làm điều đó chỉ để dọn sạch một số không gian TẠM THỜI trong main.cpp cho đến khi tôi quyết định cách tổ chức tệp vào các thư viện cùng với .hpp's thích hợp. Có một ý tưởng tốt hơn làm thế nào để làm điều này?
Slava V

1
Thuật ngữ chính xác trong C ++ là hàm thành viên, không phải phương thức. Không có "phương pháp" trong C ++ hợp pháp. Phương pháp là một thuật ngữ OO chung. C ++ thực hiện chúng thông qua các chức năng thành viên.
Brian Neal

14

định nghĩa hàm tĩnh sẽ đánh dấu biểu tượng này là nội bộ. Vì vậy, nó sẽ không hiển thị để liên kết từ bên ngoài, mà chỉ các chức năng trong cùng một đơn vị biên dịch, thường là cùng một tệp.


7

Hàm tĩnh là một hàm có thể được gọi trên chính lớp đó, trái ngược với một thể hiện của lớp.

Ví dụ: không tĩnh sẽ là:

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

Phương thức này hoạt động trên một thể hiện của lớp, không phải chính lớp đó. Tuy nhiên, bạn có thể có một phương thức tĩnh có thể hoạt động mà không cần có một thể hiện. Điều này đôi khi được sử dụng trong mẫu Factory:

Person* tom = Person::createNewPerson();

2
Dường như với tôi rằng bạn đang nói về "phương thức" tĩnh chứ không phải "hàm" ??
Slava V

Tôi giả sử bạn đang đề cập đến các hàm tĩnh trong một lớp.
Vẹt

Nếu tôi đã biết "phương thức" được gọi là "hàm phương thức" trong C ++, tôi sẽ rõ hơn về điều đó. Chà, giờ thì tôi làm rồi :) Dù sao cũng cảm ơn
Slava V

5
Không có "phương thức" nào trong C ++, chỉ có các hàm. Tiêu chuẩn C ++ không bao giờ đề cập đến "phương thức", chỉ "chức năng".
Brian Neal

1
@Puddle Tôi biết bạn đang nói gì nhưng trong tiêu chuẩn C ++ không có định nghĩa về "phương thức". C ++ chỉ có chức năng, các loại. "Phương pháp" là một thuật ngữ OO chung và được sử dụng trong các ngôn ngữ khác và không chính thức trong C ++. Một phương thức được chính thức gọi là "hàm thành viên" trong C ++.
Brian Neal

7

Nit nhỏ: các hàm tĩnh được hiển thị cho một đơn vị dịch, trong hầu hết các trường hợp thực tế là tệp mà hàm được xác định. Lỗi bạn nhận được thường được gọi là vi phạm Quy tắc Một Định nghĩa.

Tiêu chuẩn có thể nói một cái gì đó như:

"Mỗi chương trình sẽ chứa chính xác một định nghĩa của mọi hàm hoặc đối tượng phi tuyến được sử dụng trong chương trình đó; không cần chẩn đoán."

Đó là cách C nhìn vào các hàm tĩnh. Điều này không được chấp nhận trong C ++.

Ngoài ra, trong C ++, bạn có thể khai báo các hàm thành viên tĩnh. Đây hầu hết là các siêu dữ liệu tức là chúng không mô tả / sửa đổi hành vi / trạng thái của một đối tượng cụ thể mà chỉ hành động trên toàn bộ lớp. Ngoài ra, điều này có nghĩa là bạn không cần tạo một đối tượng để gọi hàm thành viên tĩnh. Hơn nữa, điều này cũng có nghĩa là, bạn chỉ có quyền truy cập vào các biến thành viên tĩnh từ bên trong một hàm như vậy.

Tôi muốn thêm vào ví dụ của Parrot mẫu Singleton dựa trên loại hàm thành viên tĩnh này để nhận / sử dụng một đối tượng trong suốt vòng đời của chương trình.


7

Câu trả lời cho hàm tĩnh phụ thuộc vào ngôn ngữ:

1) Trong các ngôn ngữ không có OOPS như C, điều đó có nghĩa là chức năng chỉ có thể truy cập được trong tệp được xác định.

2) Trong các ngôn ngữ có OOPS như C ++, điều đó có nghĩa là hàm có thể được gọi trực tiếp trên lớp mà không cần tạo một thể hiện của nó.


Đây không phải là sự thật. Giải thích về đoạn thứ hai của bạn đề cập đến " các hàm thành viên tĩnh " của một lớp, không phải là " các hàm tĩnh ". Trong C ++, một hàm đủ điều kiện staticcũng có phạm vi tệp, giống như trong C.
RobertS hỗ trợ Monica Cellio

0

Vì hàm tĩnh chỉ hiển thị trong tệp này. Trên thực tế, trình biên dịch có thể thực hiện một số tối ưu hóa cho bạn nếu bạn khai báo "tĩnh" cho một số chức năng.

Đây là một ví dụ đơn giản.

C chính

#include <stdio.h>

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

int main()
{
    int ret = 0;

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

Và biên dịch với

gcc -o main main.c

Bạn sẽ thấy nó thất bại. Bởi vì bạn thậm chí không thực hiện hàm ghost ().

Nhưng nếu chúng ta sử dụng lệnh sau.

gcc -DTEST -O2 -o main main.c

thành công , và chương trình này có thể được thực hiện bình thường.

Tại sao? Có 3 điểm chính.

  1. -O2: Mức tối ưu hóa trình biên dịch ít nhất là 2.
  2. -DTEST: Xác định TEST, vì vậy test () sẽ không được gọi.
  3. Xác định "tĩnh" để kiểm tra ().

Chỉ khi 3 điều kiện này hoàn toàn đúng, bạn mới có thể vượt qua quá trình biên dịch. Do khai báo "tĩnh" này, trình biên dịch có thể xác nhận rằng test () sẽ KHÔNG BAO GIỜ được gọi trong tệp khác. Trình biên dịch của bạn có thể loại bỏ test () khi biên dịch. Vì chúng ta không cần test (), nên việc ghost () được xác định hay thực hiện không thành vấn đề.


0

" A là gì‘ staticchức năng’trong C? "

Hãy cùng bắt đầu lại từ đầu.

Tất cả đều dựa trên một thứ gọi là "liên kết":

" Một mã định danh được khai báo trong các phạm vi khác nhau hoặc trong cùng một phạm vi nhiều lần có thể được thực hiện để tham chiếu đến cùng một đối tượng hoặc chức năng bằng một quá trình gọi là liên kết. 29) Có ba loại liên kết: bên ngoài, bên trong và không có gì. "

Nguồn: C18, 6.2.2 / 1


"Trong tập hợp các đơn vị dịch thuật và thư viện cấu thành toàn bộ chương trình, mỗi khai báo của một mã định danh cụ thể có liên kết ngoài biểu thị cùng một đối tượng hoặc chức năng. Trong một đơn vị dịch thuật, mỗi khai báo của một mã định danh có liên kết bên trong biểu thị cùng một đối tượng hoặc chức năng . Mỗi tuyên bố của một định danh không có liên kết biểu thị một thực thể duy nhất. "

Nguồn: C18, 6.2.2 / 2


Nếu một hàm được định nghĩa mà không có bộ chỉ định lớp lưu trữ, thì hàm này có externliên kết al theo mặc định:

"Nếu khai báo một mã định danh cho một hàm không có bộ xác định lớp lưu trữ, thì mối liên kết của nó được xác định chính xác như thể nó được khai báo với bên ngoài của trình xác định lớp lưu trữ ."

Nguồn: C18, 6.2.2 / 5

Điều đó có nghĩa là - nếu chương trình của bạn chứa một số đơn vị dịch / tệp nguồn ( .choặc .cpp) - chức năng sẽ hiển thị trong tất cả các đơn vị dịch / tệp nguồn mà chương trình của bạn có.

Đây có thể là một vấn đề trong một số trường hợp. Điều gì sẽ xảy ra nếu bạn muốn sử dụng hai hàm (định nghĩa) khác nhau, nhưng có cùng tên hàm trong hai bối cảnh khác nhau (thực tế là bối cảnh tệp).

Trong C C ++, trình staticphân loại lớp lưu trữ được áp dụng cho một hàm ở phạm vi tệp (không phải là hàm thành viên tĩnh của một lớp trong C ++ hoặc một hàm trong một khối khác) giờ đây để trợ giúp và biểu thị rằng hàm tương ứng chỉ hiển thị bên trong đơn vị dịch thuật / tệp nguồn được xác định trong và không phải trong các TLU / tệp khác.

"Nếu việc khai báo một định danh phạm vi tệp cho một đối tượng hoặc một hàm chứa tĩnh của trình xác định lớp lưu trữ , thì định danh có liên kết bên trong. 30)"


30) Một khai báo hàm có thể chứa specifierstaticonly lưu trữ nếu nó ở phạm vi tệp; xem 6.7.1.

Nguồn: C18, 6.2.2 / 3


Do đó, statichàm A chỉ có ý nghĩa, iff:

  1. Chương trình của bạn được chứa một số đơn vị dịch / tệp nguồn ( .choặc .cpp).

  2. Bạn muốn giới hạn phạm vi của một chức năng đối với tệp, trong đó chức năng cụ thể được xác định.

Nếu không phải cả hai yêu cầu này đều khớp, bạn không cần phải suy nghĩ về việc đủ điều kiện một chức năng như static.


Ghi chú bên:

  • Như đã đề cập, statichàm A hoàn toàn không có sự khác biệt nào giữa C và C ++, vì đây là một tính năng C ++ được thừa hưởng từ C.

    Không có vấn đề gì trong cộng đồng C ++, có một cuộc tranh luận đau lòng về sự mất giá của các hàm đủ điều kiện staticso với việc sử dụng các không gian tên không được đặt tên thay vào đó, lần đầu tiên được khởi tạo bởi một đoạn bị đặt sai trong tiêu chuẩn C ++ 03, tuyên bố sử dụng các hàm tĩnh như không dùng nữa đã sớm được sửa đổi bởi chính ủy ban và bị loại bỏ trong C ++ 11.

    Điều này đã được đặt ra cho các câu hỏi SO khác nhau:

    Không gian tên không tên / ẩn danh so với các hàm tĩnh

    Sự vượt trội của không gian tên không tên so với tĩnh?

    Tại sao một không gian tên không tên là một thay thế "vượt trội" cho tĩnh?

    Khấu hao từ khóa tĩnh ... không còn nữa?

    Trên thực tế, nó không bị phản đối theo tiêu chuẩn C ++. Vì vậy, việc sử dụng các staticchức năng vẫn là hợp pháp. Ngay cả khi các không gian tên không tên có lợi thế, cuộc thảo luận về việc sử dụng hoặc không sử dụng các hàm tĩnh trong C ++ phải tuân theo một tâm trí (dựa trên ý kiến) và không phù hợp với trang web này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.