我有一个具有不同成员函数签名的类。根据一些要求(具体来说是为了优化执行时间),我需要在特定时间调用上述方法。我打算创建一个以下类型的结构:
#include <iostream>
class A
{
public:
void Show() {std::cout << "Called 0" << std::flush << std::endl;}
int Show1() {std::cout << "Called 1" << std::flush << std::endl;}
double Show2(char z) {std::cout << "Called 2" << std::flush << std::endl;}
float Show3(int op, float x) {std::cout << "Called 3" << std::flush << std::endl;}
};
struct details
{
int type ; /* methods to be called resp : 0 =Show,1=Show1,2=Show2,3=Show3*/
union
{
void (A::*fn)();
int (A::*fn1)();
double (A::*fn2)(char z);
float (A::*fn3)(int op, float x);
}fnptr;
};
int main()
{
struct details d1 [4] ;
d1[0].type = 0;
d1[0].fnptr.fn = &A::Show;
A a1;
(a1.*(d1[0].fnptr.fn))();
d1[0].type = 1;
d1[0].fnptr.fn1 = &A::Show1;
(a1.*(d1[0].fnptr.fn1))();
d1[0].type = 1;
d1[0].fnptr.fn2 = &A::Show2;
(a1.*(d1[0].fnptr.fn2))('a');
d1[0].type = 4;
d1[0].fnptr.fn3 = &A::Show3;
(a1.*(d1[0].fnptr.fn3))(2,3.14);
}
MINGW64 /c/work
$ c++ try.cpp -std=c++11
MINGW64 /c/work
$ ./a.exe
Called 0
Called 1
Called 2
Called 3
但是我无法初始化数组:
struct details d1 [4] = {{0, &A::Show}, {1, &A::Show1}, {2, &A::Show2}, {3, &A::Show3}};
说明编译错误
int main()
{
struct details d1 [4] = {{0, &A::Show}, {1, &A::Show1}, {2, &A::Show2}, {3, &A::Show3}};
}
try.cpp: In function 'int main()':
try.cpp:26:87: error: cannot convert 'int (A::*)()' to 'void (A::*)()' in initialization
struct details d1 [4] = {{0, &A::Show}, {1, &A::Show1}, {2, &A::Show2}, {3, &A::Show3}};
^
try.cpp:26:87: error: cannot convert 'double (A::*)(char)' to 'void (A::*)()' in initialization
try.cpp:26:87: error: cannot convert 'float (A::*)(int, float)' to 'void (A::*)()' in initialization
如何正确初始化结构?
答案 0 :(得分:4)
但是我无法初始化数组:
struct details d1 [4] = {{0, &A::Show}, {1, &A::Show1}, {2, &A::Show2}, {3, &A::Show3}};
使用该语法初始化union
时,该值必须与其第一个成员对应。在您的情况下,第一个成员是fn
,其类型为void (A::*)()
。
该行相当于:
struct details d1 [4] = {{0}, {1}, {2}, {3}};
d1[0].fn = &A::Show;
d1[1].fn = &A::Show1;
d1[2].fn = &A::Show2;
d1[3].fn = &A::Show3;
这解释了编译器错误。
Documentation from the standard:
当使用大括号括起初始化程序初始化union时,大括号应仅包含union的第一个非静态数据成员的initializer子句。 [示例:
union u { int a; const char* b; }; u a = { 1 }; u b = a; u c = 1; // error u d = { 0, "asdf" }; // error u e = { "asdf" }; // error
- 结束示例]
答案 1 :(得分:4)
目前,在C ++中,当联合为aggregate initialized时,只会初始化第一个非静态数据成员(可以是,或)。你无法解决这个问题。
好消息是,从C++20开始,您将能够select an active member during aggregate initialization。所以,这种语法应该可以在几年内完成。 : - )
details d1 [4] = {{0, {.fn = &A::Show}}, {1, {.fn1 = &A::Show1}}, {2, { .fn2 = &A::Show2}}, {3, { .fn3 = &A::Show3}}};