2012-05-16 7 views
12

Tôi có tuyên bố sau đây của một số thành viên const tĩnhthành viên const Tại sao tĩnh không thể xuất hiện trong một biểu thức hằng như 'tắc'

.h

class MyClass : public MyBase 
{ 
public: 
    static const unsigned char sInvalid; 
    static const unsigned char sOutside; 
    static const unsigned char sInside; 
    //(41 more ...) 
} 

cpp

const unsigned char MyClass::sInvalid = 0; 
const unsigned char MyClass::sOutside = 1; 
const unsigned char MyClass::sInside = 2; 
//and so on 

Tại một số điểm tôi muốn sử dụng những giá trị đó trong một công tắc như:

unsigned char value; 
... 
switch(value) { 
    case MyClass::sInvalid : /*Do some ;*/ break; 
    case MyClass::sOutside : /*Do some ;*/ break; 
    ... 
} 

Nhưng tôi nhận được lỗi trình biên dịch sau: lỗi: 'MyClass :: sInvalid' không thể xuất hiện trong biểu thức hằng số.

Tôi đã đọc các công cụ chuyển đổi không thể xuất hiện liên tục khác và không tìm thấy câu trả lời cho tôi vì tôi không hiểu lý do tại sao những người đó static const unsigned char không phải là biểu thức liên tục.

Tôi đang sử dụng gcc 4.5.

Trả lời

17

Những vấn đề bạn thấy là do thực tế rằng đây

static const unsigned char sInvalid; 

không thể là một thời gian biểu cố định biên dịch, kể từ khi biên dịch không biết giá trị của nó. Khởi tạo chúng trong tiêu đề như sau:

class MyClass : public MyBase 
{ 
public: 
    static const unsigned char sInvalid = 0; 
    ... 

và nó sẽ hoạt động.

+0

-1'd do nhầm lẫn. Bạn nên xác định rằng việc khởi tạo nên được ** bên trong ** định nghĩa lớp, không chỉ là tiêu đề.Nếu bạn khởi tạo chúng trong tiêu đề, nhưng bên ngoài lớp, bạn sẽ nhận được các lỗi liên kết. –

+0

@LuchianGrigore: OK, tôi đã nói rõ điều đó. – jpalecek

+4

+1 cho một giải pháp hợp lệ, nhưng tôi vẫn điều enum là tốt hơn ở đây. –

9

Giá trị thực sự là const, nhưng chúng không phải là hằng số biên dịch.

Điều kiện A switch được giải quyết tại thời gian biên dịch, không phải thời gian chạy. Bạn có thể khởi tạo sInvalid cho bất kỳ giá trị nào, miễn là nó chỉ một lần và switch sẽ không bao giờ biết về nó cho đến khi chạy.

Dường như bạn nên sử dụng enum s thay vì hằng số static. Bên cạnh thực tế là nó sẽ làm việc, nó có vẻ thích hợp hơn thiết kế khôn ngoan.

+0

Cảm ơn lời giải thích có giá trị của bạn! Enum là lựa chọn đầu tiên của tôi, nhưng tôi đang sử dụng những thứ liên tục ở nơi khác trong hoạt động cắn-khôn ngoan và trong nội dung mảng lớn, tôi thực sự cần chúng là 'unsigned char'. Tôi không bao giờ tìm thấy một cách để làm cho nó hoạt động đúng cách mà không sử dụng các loại 'unsigned char' rõ ràng. Sử dụng Enum mặc định và đưa nó vào 'unsigned char' ở khắp mọi nơi, làm cho mã không thể đọc được mà tôi cam với giải pháp này. – vrince

+0

bạn có thể giải thích sự khác biệt giữa hằng số hằng số và hằng số biên dịch không? (hoặc liên kết đến một lời giải thích?) – dbliss

2

Bạn có thể sử dụng lừa enum để làm hằng họ thời gian biên dịch:

class MyClass 
{ 
public: 
    enum { 
     sInvalid, 
     sOutside, 
     sInside, 
     //(41 more ...) 
    }; 
}; 

Trong code của bạn, bạn vẫn có thể sử dụng enum để assing để char unsigned, một cái gì đó như thế này:

int main(int argc, char *argv[]) 
{ 
    unsigned char buf[32]; 
    buf[0] = MyClass::sInvalid; //int to unsigned char 
    return buf[0]; //Cast back to int (and avoid a warning a -Wall) 
} 

Và sử dụng MyClass::sInvalid trong câu lệnh swith của bạn.

+0

Vâng tôi thực sự cần chúng là 'unsigned char' và tôi không thể tạo 'enum MyEnum: unsigned char' làm việc với tất cả phiên bản trình biên dịch chúng tôi đang sử dụng. – vrince

+0

Switch sẽ không phiền. Xem chỉnh sửa của tôi, biên dịch với g ++ 4.6.1 -Wall – ixe013