2013-06-06 32 views
11

Tôi có một lớp học chỉ sử dụng địa phương (ví dụ, đối phó của nó là chỉ có C++ File nó được định nghĩa trong)const tĩnh trong C++ lớp: undefined tham khảo

class A { 
public: 
    static const int MY_CONST = 5; 
}; 

void fun(int b) { 
    int j = A::MY_CONST; // no problem 
    int k = std::min<int>(A::MY_CONST, b); // link error: 
              // undefined reference to `A::MY_CONST` 
} 

Tất cả các mã cư trú tại cùng C++ tệp. Khi biên dịch bằng cách sử dụng VS trên cửa sổ, không có vấn đề gì cả.
Tuy nhiên, khi biên dịch trên Linux, tôi chỉ gặp lỗi undefined reference cho câu lệnh thứ hai.

Mọi đề xuất?

luận
+0

Không chỉ định đối số mẫu chức năng. Chỉ cần 'std :: min (A :: MY_CONST, b)', nó sạch hơn. –

+0

@KerrekSB - nói chung bạn nói đúng. Tôi đã sửa đổi ví dụ này từ mã của tôi. Có 'b' không phải là' int' và do đó tôi cần xác định rõ ràng đối số mẫu. –

+0

câu trả lời liên quan (không phải dup) trạng thái đặc biệt của 'static ints': http://stackoverflow.com/a/1312267/2379182 –

Trả lời

11

std::min<int> 's đều const int& (không chỉ int), ví dụ: tài liệu tham khảo để int. Và bạn không thể chuyển một tham chiếu đến A::MY_CONST vì nó là không được xác định (chỉ được khai báo).

Cung cấp một định nghĩa trong file .cpp, bên ngoài lớp:

class A { 
public: 
    static const int MY_CONST = 5; // declaration 
}; 

const int A::MY_CONST; // definition (no value needed) 
+0

câu trả lời xuất sắc: giải thích và giải pháp tốt. Cảm ơn! –

+0

@djf Thật vậy, có lẽ đó là lý do tại sao tôi không thể tạo lại lỗi. (Nhưng tôi vẫn nghĩ rằng nó tránh được các vấn đề tiềm tàng để luôn cung cấp một định nghĩa; nếu không cần trình biên dịch sẽ xóa nó đi. Nếu bạn _want_ ngăn chặn lấy địa chỉ của nó, bạn chỉ có thể sử dụng thủ thuật 'enum' cũ.) –

+0

Để hoàn thành' static const int' được xử lý khác với các kiểu dữ liệu khác, xem [câu trả lời này] (http://stackoverflow.com/a/1312267/2379182). –

5
// initialize static constants outside the class 

class A { 
public: 
    static const int MY_CONST; 
}; 

const int A::MY_CONST = 5; 

void fun(int b) { 
    int j = A::MY_CONST; // no problem 
    int k = std::min<int>(A::MY_CONST, b); // link error: 
              // undefined reference to `A::MY_CONST` 
} 
+0

Điều này giải quyết vấn đề bởi vì nó cung cấp một định nghĩa. Mã gốc cũng sẽ hoạt động nếu có định nghĩa, giống như định nghĩa ở đây nhưng không có bộ khởi tạo. –

0

Tôi gặp một tình huống rất lạ

template<class T> class Strange { 

public: 
    static const char gapchar='-'; 
    }; 

template<class T> void Strange<T> method1 { 
     char tmp = gapchar; 
} 

template<class T> void Strange<T> method2 { 
    char tmp = gapchar; 
} 

tôi bao gồm các lớp trên, nó đã làm việc nhiều năm.

Tôi đã thêm phương thức khác, về bản chất là chữ ký giống nhau và chỉ đọc khoảng cách.

Tôi bị lỗi không xác định chỉ cho phương pháp thứ ba, ngay cả khi tôi đang sử dụng cả ba phương pháp.

Sau đó, tôi đã thay đổi cách tôi khởi tạo các biến tĩnh bởi

không khởi tạo trong định nghĩa lớp:

static const char gapchar; 

template<class T> const char Strange<T>::gapchar='-'; 

này đã giải quyết được vấn đề. Tôi không thể hiểu tại sao cách cũ của khởi tạo kiểu int hoặc char (chỉ có hai kiểu được phép) bên trong lớp phần định nghĩa ngừng hoạt động chỉ với một trong các phương thức chứ không phải cho các phương thức khác.

3

Để giải thích những gì đang xảy ra ở đây:

Bạn tuyên bố static const nguyên bên trong lớp, tính năng này "" là ở đây để có thể sử dụng nó như biểu thức hằng, tức là. đối với kích thước mảng cục bộ, các tham số không kiểu mẫu, vv .. Nếu trình biên dịch muốn sử dụng biểu thức hằng số , nó phải có khả năng thấy giá trị của nó trong đơn vị dịch đó.

9,5/3

Nếu một const tĩnh thành viên dữ liệu non-volatile là không thể thiếu hoặc liệt kê loại, tuyên bố của nó trong lớp định nghĩa fi de thể chỉ định một cú đúp-hoặc-bằng-initializer trong đó mỗi initializer -nhưng đó là một biểu thức gán là một biểu thức liên tục (5.19).Một thành viên dữ liệu tĩnh của kiểu chữ có thể được khai báo trong trường hợp lớp học với đặc tả constexpr; nếu vậy, khai báo của nó phải xác định một bộ khởi tạo dấu ngoặc đơn hoặc bằng nhau , trong đó mỗi mệnh đề khởi tạo là một biểu thức gán là một biểu thức không đổi. [Lưu ý: Trong cả hai trường hợp này, thành viên có thể xuất hiện trong biểu thức không đổi. - chú thích cuối cùng] Thành viên vẫn sẽ được xác định trong phạm vi không gian tên nếu được sử dụng không đúng (3.2) trong chương trình và phạm vi không gian tên không được chứa bộ khởi tạo.

odr-sử dụng có nghĩa là để tạo thành tham chiếu đến biến đó hoặc lấy địa chỉ của nó.

std::min lấy tham số của nó theo tham chiếu, vì vậy chúng là odr-used.

Giải pháp:

Xác định!

class A 
{ 
    static const int a = 5; 
}; 

const int A::a; //definition, shall not contain initializer 
Các vấn đề liên quan