2014-09-04 14 views

Trả lời

5

Có hai khía cạnh cho câu hỏi này

Aspect 1

C++ mảng có kích thước cố định, kích thước của mà cần phải được biết đến trong thời gian biên dịch. Nếu quyết định cần được trì hoãn trong thời gian chạy, biểu thức mảng trở nên không đúng định dạng.

Aspect 2

Khai báo một biến thành viên như không tĩnh làm cho nó một biến Ví dụ, giá trị trong đó chỉ tồn tại một khi đối tượng được khởi tạo được thực hiện trong suốt thời gian chạy. Một biến tĩnh là một biến lớp, giá trị có thể được xác định trong thời gian biên dịch.

Ví dụ cụ thể của bạn trở thành nghịch lý trứng gà cổ điển.

class armon 
{ 
    static const int maxSize=10;  

    int array[maxSize]; 

} 
  • Để nhanh chóng lớp học của bạn armon, bạn cần phải biết kích thước của nó.
  • Để biết kích thước của nó, bạn cần biết kích thước của từng thành viên. Trong trường hợp cụ thể của bạn, bạn cần phải biết kích thước của mảng.
  • Để biết kích thước của mảng, bạn cần phải biết giá trị của biến phụ thuộc maxSize.
  • Để truy cập biến phụ thuộc maxSize, bạn cần khởi tạo lớp armon.
  • Để khởi tạo lớp học của bạn armon, bạn cần biết kích thước của nó.

Vì vậy, biến phụ thuộc kích thước mảng của bạn phải là một biểu hiện thường xuyên, mà trong trường hợp cụ thể của bạn phải là một biến tĩnh,

14

Nó không là tĩnh, nhưng phải là biểu thức không đổi .

C++ chuẩn § 8.3.4 [dcl.array] (tôi nhấn mạnh):

Nếu không đổi biểu thức (5.19) có mặt, nó sẽ là một chuyển đổi biểu thức hằng số kiểu std :: size_t và giá trị của nó sẽ lớn hơn không


Đó là, sau đây cũng là hợp lệ:

constexpr std::size_t Size() { return 10; }; 

struct Y 
{ 
    int array[Size()]; 
}; 

Lưu ý:

Kể từ khi biên dịch cần phải biết kích thước của lớp, bạn không thể làm điều này:

struct Y 
{ 
    const int size = 10; 
    int array[size]; 
}; 

Có thể làm cho các trường hợp khác nhau của Y có kích cỡ khác nhau.

Cũng lưu ý rằng trong bối cảnh này, int array[size]không một biểu thức hằng số, vì nó làm cho sử dụng this, xem C++ phần tiêu chuẩn § 5,19 [expr.const]:

Một điều kiện thể hiện e là một biểu thức liên tục cốt lõi trừ khi việc đánh giá e, tuân theo các quy tắc của máy trừu tượng (1.9), sẽ đánh giá một trong các biểu thức sau:

- (5.1.1), trừ một hàm constexpr hoặc một cấu trúc constexpr tor đang được đánh giá là một phần của e;

(đánh giá của size thực sự this->size là)

+0

này là do thực tế là trình biên dịch có thể dự trữ bộ nhớ trong biên dịch. Một lời giải thích tốt [ở đây] (http://stackoverflow.com/questions/21350478/what-does-memory-allocated-at-compile-time-really-mean) – lifeOfPI

+0

Bạn cũng cần giải thích tại sao 'const int maxSize = 10 ; 'không được coi là cung cấp cho một biểu thức liên tục, nhưng' static const int maxSize = 10' là –

+0

@MattMcNabb chắc chắn, chú thích thêm – quantdev

1

Nó không phải là tĩnh, nó phải là không đổi.

Khi bạn khai báo hằng số bên trong một lớp, bạn sẽ tạo một hằng số cho mỗi cá thể của lớp.

Ngoài ra nếu maxSize của bạn chỉ là const, bạn sẽ phải intialize nó trong danh sách khởi tạo constructor vì const maxSize được coi là biến có giá trị bạn không thể thay đổi.

Bên trong một lớp học const từ khóa có nghĩa là "Đây là hằng số trong thời gian tồn tại lỗ của đối tượng này". Các đối tượng khác nhau của cùng một lớp có thể có các giá trị khác nhau cho hằng số đó.

Nhưng khi đó là hằng số tĩnh, sẽ có chỉ một hằng số cho tất cả các phiên bản của lớp. Điều này có nghĩa là bạn phải khởi tạo giá trị hằng số trên cùng một dòng nơi bạn định nghĩa nó.

+0

"nếu maxSize của bạn chỉ là const bạn sẽ phải intialize nó trong danh sách khởi tạo constructor" là sai! Nó cũng có thể là một biến phạm vi mà không được khởi tạo trong danh sách khởi tạo. "Bên trong một từ khóa const lớp học có nghĩa là" Đây là một hằng số trong suốt thời gian tồn tại lỗ của đối tượng này "" cũng sai. Nó chỉ là một "gợi ý" cho lập trình viên. Hãy suy nghĩ về 'const_cast <>' – lifeOfPI

+2

@lifeOfPI: Nó không chỉ là một gợi ý. Bạn không thể bỏ đi const_ness và sử dụng đối tượng theo cách không const. Đó sẽ là hành vi không xác định, và có thể phá vỡ theo những cách khá bất ngờ. Một cách _expected_ trong đó nó phá vỡ là trình biên dịch có thể đã tạo ra nhiều bản sao của một hằng số và bạn chỉ thay đổi một bản sao. – MSalters

+0

Bạn không phải khởi tạo nó trong danh sách khởi tạo hàm tạo, ví dụ: 'int count = 0;' trong mã OP. –

Các vấn đề liên quan