在 c++ 中使用字符串变量选择静态类结构,而不带对象

Сalling a static class structure with string variables without an object in c++

本文关键字:结构 对象 静态类 选择 c++ 变量 字符串      更新时间:2023-10-16

有必要以代码中描述的格式接收数据,但问题出在字符串变量的操作上。如何避免错误?

class Class1
{
public:
Class1() = delete ;
const static int x = 1;
static struct ZZ {
const static int z1 = 1;
const static QString z2 = "word";
} z;
};
int main(int argc, char* argv[])
{
QCoreApplication a(argc, argv);
qDebug() << Class1::z.z2;
return a.exec();
}

错误:

class1.h:13: ошибка: in-class initialization of static data member 'const QString Class1::ZZ::z2' of non-literal type
const static QString z2 = "word";
^~
class1.h:13: ошибка: call to non-constexpr function 'QString::QString(const char*)'
const static QString z2 = "word";
^~~~~~

来源 github.com

免责声明:

我的第一印象是,这段代码滥用了classstructnamespace实际上是为了什么而发明的。

也就是说,答案集中在 OPs 代码中static数据成员的技术问题上。


为了重现该问题,我制作了以下类似示例:

#include <iostream>
#include <string>
class Class1
{
public:
Class1() = delete ;
const static int x = 1;
static struct ZZ {
static const int z1 = 1;
static const std::string z2 = "word";
} z;
};
int main(int argc, char* argv[])
{
std::cout << Class1::z.z2;
}

输出:

main.cpp:11:34: error: in-class initialization of static data member 'const string Class1::ZZ::z2' of non-literal type
11 |         static const std::string z2 = "word";
|                                  ^~
main.cpp:11:39: error: temporary of non-literal type 'const string' {aka 'const std::__cxx11::basic_string<char>'} in a constant expression
11 |         static const std::string z2 = "word";
|                                       ^~~~~~

科里鲁的现场演示

恕我直言,这与 OP 问题足够接近。

TL;DR:问题是static成员变量必须显式定义(非内联)或重新标记为inline

因此,我的修复程序如下所示:

#include <iostream>
#include <string>
class Class1
{
public:
Class1() = delete ;
const static int x = 1;
inline static struct ZZ {
static const int z1 = 1;
inline static const std::string z2 = "word";
} z = ZZ{};
};
int main(int argc, char* argv[])
{
std::cout << Class1::x << 'n'
<< Class1::z.z1 << 'n'
<< Class1::z.z2 << 'n';
}

输出:

1
1
word

科里鲁的现场演示

注意:

虽然inline对于struct ZZstd::string是必需的,但对于整型可以省略。因此,static const int z1 = 1;将被接受而没有投诉(不以inline为前缀)。

延伸阅读:

cppreference.com 上的静态数据成员


为了进行比较,相同的代码在没有inline的情况下工作:

#include <iostream>
#include <string>
class Class1
{
public:
Class1() = delete ;
const static int x = 1;
static struct ZZ {
static const int z1 = 1;
static const std::string z2;
} z;
};
//Class1::ZZ Class1::z;
const std::string Class1::ZZ::z2 = "word";
int main(int argc, char* argv[])
{
std::cout << Class1::x << 'n'
<< Class1::z.z1 << 'n'
<< Class1::z.z2 << 'n';
}

输出:

1
1
word

科里鲁的现场演示

注意:

关于const Class1::ZZ Class1::z;,我不太确定。缺少的定义可能会被省略,因为Class1::z本身永远不会使用。

为了检查这一点,我再次修改了示例:

#include <iostream>
#include <string>
class Class1
{
public:
Class1() = delete ;
const static int x = 1;
static struct ZZ {
static const int z1 = 1;
static const std::string z2;
} z;
};
Class1::ZZ Class1::z;
const std::string Class1::ZZ::z2 = "word";
std::ostream& operator << (std::ostream &out, const Class1::ZZ &z)
{
return out << z.z1 << ", " << z.z2;
}
int main(int argc, char* argv[])
{
std::cout << Class1::x << 'n'
<< Class1::z << 'n'
<< Class1::z.z1 << 'n'
<< Class1::z.z2 << 'n';
}

输出:

1
1, word
1
word

科里鲁的现场演示

注意:

注释Class1::z的定义(如上一个示例中所示)会导致链接错误。