Biểu tượng bên ngoài chưa được giải quyết trên các thành viên lớp tĩnh


129

Rất đơn giản chỉ cần đặt:

Tôi có một lớp bao gồm hầu hết các thành viên công cộng tĩnh, vì vậy tôi có thể nhóm các hàm tương tự lại với nhau mà vẫn phải được gọi từ các lớp / hàm khác.

Dù sao, tôi đã định nghĩa hai biến char không dấu tĩnh trong phạm vi công khai của lớp, khi tôi cố gắng sửa đổi các giá trị này trong cùng hàm tạo của lớp, tôi nhận được lỗi "ký hiệu bên ngoài chưa được giải quyết" khi biên dịch.

class test 
{
public:
    static unsigned char X;
    static unsigned char Y;

    ...

    test();
};

test::test() 
{
    X = 1;
    Y = 2;
}

Tôi mới sử dụng C ++ vì vậy hãy dễ dàng với tôi. Tại sao tôi không thể làm điều này?

Câu trả lời:


145

Bạn đã quên thêm các định nghĩa để khớp với khai báo X và Y của bạn

unsigned char test::X;
unsigned char test::Y;

một vài nơi. Bạn cũng có thể muốn khởi tạo một thành viên tĩnh

unsigned char test::X = 4;

và một lần nữa, bạn làm điều đó trong định nghĩa (thường là trong tệp CXX) không phải trong khai báo (thường là trong tệp .H)


4
Nếu bạn đang viết thư viện chỉ có tiêu đề, bạn có thể sử dụng kỹ thuật này để tránh tệp cpp: stackoverflow.com/questions/11709859/ chủ
Shital Shah

62

Khai báo thành viên dữ liệu tĩnh trong khai báo lớp không định nghĩa về chúng. Để xác định chúng, bạn nên làm điều này trong .CPPtệp để tránh các ký hiệu trùng lặp.

Dữ liệu duy nhất bạn có thể khai báo và định nghĩa là hằng số tĩnh tích phân. (Giá trị của enumscũng có thể được sử dụng làm giá trị không đổi)

Bạn có thể muốn viết lại mã của mình dưới dạng:

class test {
public:
  const static unsigned char X = 1;
  const static unsigned char Y = 2;
  ...
  test();
};

test::test() {
}

Nếu bạn muốn có khả năng sửa đổi các biến tĩnh của mình (nói cách khác khi không phù hợp để khai báo chúng là const), bạn có thể tách mã của bạn giữa .H.CPPtheo cách sau:

.H:

class test {
public:

  static unsigned char X;
  static unsigned char Y;

  ...

  test();
};

.CPP:

unsigned char test::X = 1;
unsigned char test::Y = 2;

test::test()
{
  // constructor is empty.
  // We don't initialize static data member here, 
  // because static data initialization will happen on every constructor call.
}

tại sao trong .CPP, đây là "unsign char test :: X = 1;" thay vì "test :: X = 1;"? biến tĩnh X đã được xác định, tại sao vẫn cần "unsign char"? @sergtk
Penny

@Penny Vì "test :: X = 1;" được hiểu là một bài tập, trong khi những gì chúng tôi đang cố gắng làm là một định nghĩa.
Anonymous1847

4

Vì đây là luồng SO đầu tiên dường như xuất hiện cho tôi khi tìm kiếm "các phần bên ngoài chưa được giải quyết với các thành viên const tĩnh" nói chung, tôi sẽ để lại một gợi ý khác để giải quyết một vấn đề với các phần bên ngoài chưa được giải quyết ở đây:

Đối với tôi, điều mà tôi quên là đánh dấu định nghĩa lớp của tôi __declspec(dllexport)và khi được gọi từ một lớp khác (bên ngoài ranh giới của lớp đó), tất nhiên tôi đã nhận được lỗi bên ngoài chưa được giải quyết.
Tuy nhiên, rất dễ quên khi bạn thay đổi một lớp người trợ giúp nội bộ sang một lớp có thể truy cập từ nơi khác, vì vậy nếu bạn đang làm việc trong một dự án được liên kết động, bạn cũng có thể kiểm tra điều đó.


2

trong trường hợp của tôi, tôi đã khai báo một biến tĩnh trong tệp .h, như

//myClass.h
class myClass
{
static int m_nMyVar;
static void myFunc();
}

và trong myClass.cpp, tôi đã thử sử dụng m_nMyVar này. Nó có lỗi LINK như:

lỗi LNK2001: ký hiệu bên ngoài chưa được giải quyết "công khai: lớp tĩnh ... Tệp cpp liên quan đến lỗi liên kết trông giống như:

//myClass.cpp
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}

Vì vậy, tôi thêm mã dưới đây vào đầu myClass.cpp

//myClass.cpp
int myClass::m_nMyVar; //it seems redefine m_nMyVar, but it works well
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}

sau đó LNK2001 biến mất.


0

Trong trường hợp của tôi, tôi đã sử dụng liên kết sai.
Nó được quản lý c ++ (cli) nhưng với xuất khẩu tự nhiên. Tôi đã thêm vào trình liên kết -> đầu vào -> tài nguyên liên kết lắp ráp dll của thư viện mà từ đó hàm được xuất. Nhưng liên kết c ++ gốc yêu cầu tệp .lib để "xem" các triển khai trong cpp một cách chính xác, vì vậy tôi đã giúp thêm tệp .lib vào trình liên kết -> đầu vào -> phụ thuộc bổ sung.
[Thông thường mã được quản lý không sử dụng xuất và nhập dll, nó sử dụng các tham chiếu, nhưng đó là tình huống duy nhất.]

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.