C++ 获取 class 成员的默认值而不创建新的 object
C++ get default value of class member without creating new object
让我们考虑一下定义:
struct ClassWithMember
{
int myIntMember = 10;
}
我想获得myIntMember
的默认值,但不要创建class
的另一个实例
// IMPOSSIBLE int myInt = ClassWithMember::myIntMember;
// MUST AVOID int myInt = ClassWithMember().myIntMember;
我知道解决方法,但不喜欢它:
struct ClassWithMember
{
static const int myIntMember_DEFAULT = 10;
int myIntMember = myIntMember_DEFAULT;
}
int myInt = ClassWithMember::myIntMember_DEFAULT;
因为它需要额外的线。而且我不能定义像 static const int *const INTEGER11_DEFAULT = 0x100088855;
这样的内联静态指针,这样的指针必须在 .cpp
文件中定义,在 .hpp
中只是声明。我的许多 class 都是 header-only,因此为此值创建多余的 .cpp
不是个好主意。
Here 是 C#
的类似问题
我将此解决方案称为 解决方法
struct ClassWithMember
{
static const int myIntMember_DEFAULT = 10;
int myIntMember = myIntMember_DEFAULT;
}
int myInt = ClassWithMember::myIntMember_DEFAULT;
对于指针来说会比较复杂
//.hpp
struct ClassWithMember
{
static AnotherClass* const myMember_DEFAULT; //=X; Assignment not allowed
AnotherClass* myMember = myMember_DEFAULT;
}
//.cpp
AnotherClass* const MyNamespace::ClassWithMember::myMember_DEFAULT = pAnotherInstance;
//usage
auto *my = ClassWithMember::myMember_DEFAULT;
我想,对您来说,这只是另一种解决方法,但我认为更实用一点(仅一点点)。
如果将默认值保存为静态方法返回的静态常量,则可以避免cpp文件中的附加行。
下面的例子在模板包装器中做了这个技巧(默认值作为模板参数和默认值;只是为了好玩)但是模板部分只是为了避免示例中的代码重复
#include <iostream>
template <typename T, T defTpl = T{}>
struct wrapperWithDef
{
static T getDefVal ()
{ static T const def { defTpl }; return def; }
T myTMember { getDefVal() };
};
int main()
{
wrapperWithDef<int> wi;
wrapperWithDef<long, 3L> wl;
wrapperWithDef<int *> wp;
// print "0, 3, (nil)" (clang++) or "0, 3, 0" (g++)
std::cout << wi.myTMember << ", " << wl.myTMember << ", "
<< wp.myTMember << std::endl;
// print "5, (nil), 1" (clang++) or "5, 0, 1" (g++)
std::cout << wrapperWithDef<unsigned, 5U>::getDefVal() << ", "
<< wrapperWithDef<long *>::getDefVal() << ", "
<< wrapperWithDef<bool, true>::getDefVal() << std::endl;
return 0;
}
让我们考虑一下定义:
struct ClassWithMember
{
int myIntMember = 10;
}
我想获得myIntMember
的默认值,但不要创建class
// IMPOSSIBLE int myInt = ClassWithMember::myIntMember;
// MUST AVOID int myInt = ClassWithMember().myIntMember;
我知道解决方法,但不喜欢它:
struct ClassWithMember
{
static const int myIntMember_DEFAULT = 10;
int myIntMember = myIntMember_DEFAULT;
}
int myInt = ClassWithMember::myIntMember_DEFAULT;
因为它需要额外的线。而且我不能定义像 static const int *const INTEGER11_DEFAULT = 0x100088855;
这样的内联静态指针,这样的指针必须在 .cpp
文件中定义,在 .hpp
中只是声明。我的许多 class 都是 header-only,因此为此值创建多余的 .cpp
不是个好主意。
Here 是 C#
的类似问题我将此解决方案称为 解决方法
struct ClassWithMember
{
static const int myIntMember_DEFAULT = 10;
int myIntMember = myIntMember_DEFAULT;
}
int myInt = ClassWithMember::myIntMember_DEFAULT;
对于指针来说会比较复杂
//.hpp
struct ClassWithMember
{
static AnotherClass* const myMember_DEFAULT; //=X; Assignment not allowed
AnotherClass* myMember = myMember_DEFAULT;
}
//.cpp
AnotherClass* const MyNamespace::ClassWithMember::myMember_DEFAULT = pAnotherInstance;
//usage
auto *my = ClassWithMember::myMember_DEFAULT;
我想,对您来说,这只是另一种解决方法,但我认为更实用一点(仅一点点)。
如果将默认值保存为静态方法返回的静态常量,则可以避免cpp文件中的附加行。
下面的例子在模板包装器中做了这个技巧(默认值作为模板参数和默认值;只是为了好玩)但是模板部分只是为了避免示例中的代码重复
#include <iostream>
template <typename T, T defTpl = T{}>
struct wrapperWithDef
{
static T getDefVal ()
{ static T const def { defTpl }; return def; }
T myTMember { getDefVal() };
};
int main()
{
wrapperWithDef<int> wi;
wrapperWithDef<long, 3L> wl;
wrapperWithDef<int *> wp;
// print "0, 3, (nil)" (clang++) or "0, 3, 0" (g++)
std::cout << wi.myTMember << ", " << wl.myTMember << ", "
<< wp.myTMember << std::endl;
// print "5, (nil), 1" (clang++) or "5, 0, 1" (g++)
std::cout << wrapperWithDef<unsigned, 5U>::getDefVal() << ", "
<< wrapperWithDef<long *>::getDefVal() << ", "
<< wrapperWithDef<bool, true>::getDefVal() << std::endl;
return 0;
}