简单地说:

我有一个主要由静态公共成员组成的类,因此我可以将仍然必须从其他类/函数调用的相似函数组合在一起。

无论如何,我在类公共作用域中定义了两个静态的无符号char变量,当我尝试在同一类的构造函数中修改这些值时,在编译时出现“无法解析的外部符号”错误。

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

    ...

    test();
};

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


我是C ++的新手,所以对我轻松一点。为什么我不能这样做?

#1 楼

如果您使用的是C ++ 17,则可以仅使用inline说明符(请参阅https://stackoverflow.com/a/11711082/55721)

如果使用的是C ++标准的较旧版本,则必须添加定义以与您的X和Y声明相匹配
unsigned char test::X;
unsigned char test::Y;

某处。您可能还想初始化静态成员
unsigned char test::X = 4;

,然后再次在定义(通常在CXX文件中)而不是在声明(通常在.H文件中)中进行此操作

评论


如果您正在编写仅标头库,则可以使用此技术来避免使用cpp文件:stackoverflow.com/questions/11709859/…

– Shital Shah
16年11月18日在18:49

#2 楼

类声明中的静态数据成员声明不是它们的定义。
要定义它们,应在.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();
};


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


评论


为什么在.CPP中,它是“ unsigned char test :: X = 1;”而不是“ test :: X = 1;”?静态变量X已经定义,为什么还需要“ unsigned char”? @sergtk

–竹enny
18-09-18在22:56



@Penny因为“ test :: X = 1;”被解释为一项任务,而我们试图做的是一个定义。

–匿名1847
4月29日下午6:42



#3 楼

由于这是通常在搜索“带有静态const成员的未解决的外部对象”时出现的第一个SO线程,因此,我将在这里留下另一个提示来解决未解决的外部对象的问题:

对我来说,我忘记的是标记我的类定义__declspec(dllexport),当从另一个类(在该类的dll的边界之外)调用时,我当然会遇到我无法解决的外部错误。
仍然,容易忘记当您将内部帮助程序类更改为可从其他地方访问的类时,因此,如果您正在动态链接的项目中工作,则最好也进行检查。

#4 楼

就我而言,我在.h文件中声明了一个静态变量,例如

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


,在myClass.cpp中,我尝试使用此m_nMyVar。出现类似LINK错误的错误:

错误LNK2001:未解决的外部符号“ public:静态类...
与链接错误相关的cpp文件如下:

所以我在myClass.cpp的顶部添加以下代码

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


然后LNK2001不见了。

#5 楼

就我而言,我使用了错误的链接。
它是用c ++(cli)管理的,但具有本机导出功能。我已向链接器->输入->程序集链接资源中添加了从中导出函数的库的dll。但是本机c ++链接需要.lib文件才能正确“查看” cpp中的实现,因此对我来说,这有助于将.lib文件添加到链接器->输入->其他依赖项。
[通常,托管代码不使用dll导出和导入,而是使用引用,但这是唯一的情况。]