สัญลักษณ์ภายนอกที่ไม่ได้รับการแก้ไขบนสมาชิกคลาสแบบคงที่


129

ใส่ง่ายมาก:

ฉันมีคลาสที่ประกอบด้วยสมาชิกสาธารณะแบบคงที่เป็นส่วนใหญ่ดังนั้นฉันจึงสามารถจัดกลุ่มฟังก์ชันที่คล้ายกันเข้าด้วยกันซึ่งยังต้องถูกเรียกจากคลาส / ฟังก์ชันอื่น ๆ

อย่างไรก็ตามฉันได้กำหนดตัวแปรถ่านที่ไม่ได้ลงชื่อแบบคงที่สองตัวแปรในขอบเขตสาธารณะของคลาสของฉันเมื่อฉันพยายามแก้ไขค่าเหล่านี้ในตัวสร้างคลาสเดียวกันฉันได้รับข้อผิดพลาด "สัญลักษณ์ภายนอกที่ไม่ได้รับการแก้ไข" ในการคอมไพล์

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

    ...

    test();
};

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

ฉันยังใหม่กับ C ++ ดังนั้นฉันจึงเป็นเรื่องง่าย ทำไมฉันทำไม่ได้

คำตอบ:


145

คุณลืมเพิ่มคำจำกัดความเพื่อให้ตรงกับการประกาศ X และ Y ของคุณ

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

บางแห่ง. คุณอาจต้องการเริ่มต้นสมาชิกแบบคงที่

unsigned char test::X = 4;

และอีกครั้งคุณทำเช่นนั้นในคำจำกัดความ (โดยปกติจะอยู่ในไฟล์ CXX) ไม่ได้อยู่ในการประกาศ (ซึ่งมักอยู่ในไฟล์. H)


4
หากคุณกำลังเขียนไลบรารีเฉพาะส่วนหัวคุณสามารถใช้เทคนิคนี้เพื่อหลีกเลี่ยงไฟล์ cpp: stackoverflow.com/questions/11709859/…
Shital Shah

62

การประกาศสมาชิกข้อมูลคงที่ในการประกาศคลาสไม่ใช่คำจำกัดความของพวกเขา ในการกำหนดคุณควรทำสิ่งนี้ใน.CPPไฟล์เพื่อหลีกเลี่ยงสัญลักษณ์ที่ซ้ำกัน

ข้อมูลเดียวที่คุณสามารถประกาศและกำหนดคือค่าคงที่ที่เป็นส่วนประกอบ (ค่าของenumsสามารถใช้เป็นค่าคงที่ได้เช่นกัน)

คุณอาจต้องการเขียนโค้ดของคุณใหม่เป็น:

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

test::test() {
}

หากคุณต้องการมีความสามารถในการปรับเปลี่ยนตัวแปรคงที่ของคุณ (กล่าวอีกนัยหนึ่งคือเมื่อไม่เหมาะสมที่จะประกาศเป็น const) คุณสามารถแยกโค้ดของคุณระหว่าง.Hและ.CPPด้วยวิธีต่อไปนี้:

.H:

class test {
public:

  static unsigned char X;
  static unsigned char Y;

  ...

  test();
};

. ซีพีพี:

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.
}

ทำไมที่นี่ใน. CPP จึงเป็น "การทดสอบถ่านที่ไม่ได้ลงชื่อ :: X = 1;" แทนที่จะเป็น "test :: X = 1;"? ตัวแปรคงที่ X กำหนดไว้แล้วทำไมยังต้องใช้ "ถ่านที่ไม่ได้ลงชื่อ" @sergtk
เพนนี

@Penny เพราะ "test :: X = 1;" ถูกตีความว่าเป็นการมอบหมายงานในขณะที่สิ่งที่เราพยายามทำคือคำจำกัดความ
Anonymous1847

4

เนื่องจากนี่เป็นเธรด SO แรกที่ดูเหมือนจะเกิดขึ้นสำหรับฉันเมื่อค้นหา "externals ที่ไม่ได้รับการแก้ไขด้วยสมาชิก const แบบคงที่" โดยทั่วไปฉันจะฝากคำใบ้อีกอย่างเพื่อแก้ปัญหาหนึ่งด้วยภายนอกที่ไม่ได้รับการแก้ไขที่นี่:

สำหรับฉันสิ่งที่ฉันลืมไปคือการทำเครื่องหมายนิยามคลาสของฉัน__declspec(dllexport)และเมื่อถูกเรียกจากคลาสอื่น (นอกขอบเขตของ dll ของคลาสนั้น) แน่นอนว่าฉันได้รับข้อผิดพลาดภายนอกที่ยังไม่ได้แก้ไข
ถึงกระนั้นก็ง่ายที่จะลืมเมื่อคุณเปลี่ยนคลาสผู้ช่วยภายในเป็นคลาสที่เข้าถึงได้จากที่อื่นดังนั้นหากคุณกำลังทำงานในโปรเจ็กต์ที่เชื่อมโยงแบบไดนามิกคุณอาจตรวจสอบด้วยเช่นกัน


2

ในกรณีของฉันฉันประกาศตัวแปรคงที่หนึ่งตัวในไฟล์. h เช่น

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

และใน myClass.cpp ฉันพยายามใช้ m_nMyVar นี้ มีข้อผิดพลาด LINK เช่น:

ข้อผิดพลาด LNK2001: สัญลักษณ์ภายนอกที่ไม่ได้รับการแก้ไข "public: static class ... ข้อผิดพลาดลิงก์ที่เกี่ยวข้องกับไฟล์ cpp มีลักษณะดังนี้:

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

ดังนั้นฉันจึงเพิ่มโค้ดด้านล่างที่ด้านบนของ 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
}

LNK2001 ก็หายไป


0

ในกรณีของฉันฉันใช้การเชื่อมโยงผิด
ได้รับการจัดการ c ++ (cli) แต่มีการส่งออกแบบเนทีฟ ฉันได้เพิ่มไปยังลิงค์เกอร์ -> อินพุต -> ทรัพยากรลิงค์แอสเซมบลี dll ของไลบรารีที่ฟังก์ชันถูกส่งออก แต่การเชื่อมโยง c ++ ดั้งเดิมต้องใช้ไฟล์. lib เพื่อ "ดู" การใช้งานใน cpp อย่างถูกต้องดังนั้นสำหรับฉันจึงช่วยเพิ่มไฟล์. lib ไปยัง linker -> input -> การอ้างอิงเพิ่มเติม
[โดยปกติแล้วรหัสที่มีการจัดการจะไม่ใช้การส่งออกและนำเข้า dll โดยจะใช้การอ้างอิง แต่นั่นเป็นสถานการณ์ที่ไม่ซ้ำกัน]

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.