创建和使用 friend class 方法的 func 指针
Creating and using func pointer to method of friend class
我有 2 个 classes:
enum class Enumtype
{
typ1,
typ2,
};
class A
{
private:
retType Func1(arg1Type, arg2Type, arg3Type);
retType Func2(arg1Type, arg2Type, arg3Type);
public:
A();
retType Func(Enumtype, arg1Type, arg2Type, arg3Type);
}
class B
{
private:
arg1Type a;
arg2Type b;
arg3Type c;
public:
int FunctionFromB(Enumtype);
}
所以主要用途是这样的:
int B::FunctionFromB(Enumtype x)
{
A* objectA;
for(int i=0; i<whatever; i++)
{
objectA->Func(x, a+i, b+(2*i), c+(3*i));
}
}
retType A::Func(Enumtype x, arg1type a, arg2type b, arg3type c)
{
switch(x)
{
case Enumtype::typ1:
return Func1(a, b, c);
case Enumtype::typ2:
return Func2(a, b, c);
default:
return Func1(a, b, c);
}
}
不幸的是,我不想 运行 切换每个循环,所以我想到了这个:
- 在class一写"friend class B"
- 删除 A::Func()
- 在 B::FunctionFromB()
中创建函数 ptr
- 在 B::FunctionFromB() 中进行切换,将提到的函数 ptr 初始化为 A::Func1 或 A::Func2。开关将类似于 A::Func()
中的开关
- 而不是 运行ning objectA->Func(x, a, b, c), 运行 objectA->functionPtr(a, b, c)
如何做到这一点?我试着用 std::function 来做到这一点,但我不知道如何正确地 declare/initialize/call 让它工作。
编辑:
我已经编辑了 FunctionFromB,因为我跳过了一个重要的部分 -> Func 被循环调用了不同的参数。
编辑2:
提供了帮助,我得到的答案是如何使用 C 风格的函数 ptr 执行此操作,但我想让它与 std::function 一起使用。我是那样做的(注意 class B 和枚举是一样的):
class A
{
private:
retType Func1(arg1Type, arg2Type, arg3Type);
retType Func2(arg1Type, arg2Type, arg3Type);
public:
A();
typedef std::function<retType(arg1Type, arg2Type, arg3Type)> funcPtr;
}
int B::FunctionFromB(Enumtype typeB)
{
A* objectA;
A::funcPtr func = nullptr;
switch(type)
{
case Enumtype::typ2:
func = std::bind(&A::Func2, objectA, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3);
break;
case Enumtype::typ2:
default:
func = std::bind(&A::Func1, objectA, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3);
break;
}
for(int i=0; i<whatever; i++)
func(a+i, b+(2*i), c+(3*i));
}
我想,它有效。如果有人在这里发现错误或更好的方法,请告诉我 ;)
你能为 EnumType 使用一个无作用域的枚举吗?
enum Enumtype
{
enumtyp1,
enumtyp2,
enumtypmax
};
如果它是一个选项,编译器会免费为您提供到 int 的转换:enumtyp1 -> 0
、enumtyp2 -> 1
、enumtypmax -> 2
(根据 3.9.2 § 10 枚举器的值或无作用域枚举类型的对象通过以下方式转换为整数
积分提升)
根据 3.9.2 §2 保证这些值
enumerator-list 被声明为常量,并且可以出现在任何需要常量的地方。枚举器定义
with = 为关联的枚举器提供常量表达式指示的值。如果第一个
枚举数没有初始化器,对应常量的值为零。枚举器定义
没有初始值设定项时,为枚举器提供通过增加前一个枚举器的值而获得的值
一个。
enum { a, b, c=0 };
enum { d, e, f=e+2 };
定义a、c、d为0,b、e为1,f为3。
然后您可以在 A 中构建 A 方法的静态数组,并使用应该比开关更简单的直接数组索引:
enum Enumtype
{
enumtyp1,
enumtyp2,
enummax
};
class A
{
private:
typedef retType (__thiscall A::*funcx)(arg1Type,arg2Type,arg3Type);
retType Func1(arg1Type, arg2Type, arg3Type);
retType Func2(arg1Type, arg2Type, arg3Type);
static funcx fp[enummax];
public:
A();
retType Func(Enumtype, arg1Type, arg2Type, arg3Type);
};
class B
{
private:
arg1Type a;
arg2Type b;
arg3Type c;
public:
int FunctionFromB(Enumtype);
};
int B::FunctionFromB(Enumtype x)
{
A* objectA;
for(int i=0; i<whatever; i++)
{
objectA->Func(x, a+i, b+(2*i), c+(3*i));
}
return whatever;
}
retType A::Func(Enumtype x, arg1Type a, arg2Type b, arg3Type c)
{
funcx f = A::fp[x];
return (this->*fp[x])(a, b, c);
}
A::funcx A::fp[enummax] = { &A::Func1, &A::Func2 };
或者,您可以直接在 B::FunctionFromB
中获取一个指针并直接重复调用它:
enum Enumtype
{
enumtyp1,
enumtyp2,
enummax
};
class A
{
public:
typedef retType (__thiscall A::*funcx)(arg1Type,arg2Type,arg3Type);
private:
retType Func1(arg1Type, arg2Type, arg3Type);
retType Func2(arg1Type, arg2Type, arg3Type);
static funcx fp[enummax];
public:
A();
friend class B;
};
class B
{
private:
arg1Type a;
arg2Type b;
arg3Type c;
A::funcx getFunc(Enumtype);
public:
int FunctionFromB(Enumtype);
};
A::funcx B::getFunc(Enumtype x){
return A::fp[x];
}
int B::FunctionFromB(Enumtype x)
{
A* objectA;
A::funcx funcPtr = getFunc(x);
for(int i=0; i<whatever; i++)
{
(objectA->*funcPtr)(a+i, b+(2*i), c+(3*i));
}
return whatever;
}
A::funcx A::fp[enummax] = { &A::Func1, &A::Func2 };
在后一种情况下,您可以避免在 A 中声明方法数组,坚持使用 EnumType 的作用域枚举,并在每次调用 B::FunctionFromB
时使用开关一次:
A::funcx B::getFunc(Enumtype x){
switch (x) {
case EnumType::typ1:
return &A::Func1;
case EnumType::typ2:
return &A::Func2;
case default:
return &A::Func1;
}
}
我有 2 个 classes:
enum class Enumtype
{
typ1,
typ2,
};
class A
{
private:
retType Func1(arg1Type, arg2Type, arg3Type);
retType Func2(arg1Type, arg2Type, arg3Type);
public:
A();
retType Func(Enumtype, arg1Type, arg2Type, arg3Type);
}
class B
{
private:
arg1Type a;
arg2Type b;
arg3Type c;
public:
int FunctionFromB(Enumtype);
}
所以主要用途是这样的:
int B::FunctionFromB(Enumtype x)
{
A* objectA;
for(int i=0; i<whatever; i++)
{
objectA->Func(x, a+i, b+(2*i), c+(3*i));
}
}
retType A::Func(Enumtype x, arg1type a, arg2type b, arg3type c)
{
switch(x)
{
case Enumtype::typ1:
return Func1(a, b, c);
case Enumtype::typ2:
return Func2(a, b, c);
default:
return Func1(a, b, c);
}
}
不幸的是,我不想 运行 切换每个循环,所以我想到了这个:
- 在class一写"friend class B"
- 删除 A::Func()
- 在 B::FunctionFromB() 中创建函数 ptr
- 在 B::FunctionFromB() 中进行切换,将提到的函数 ptr 初始化为 A::Func1 或 A::Func2。开关将类似于 A::Func() 中的开关
- 而不是 运行ning objectA->Func(x, a, b, c), 运行 objectA->functionPtr(a, b, c)
如何做到这一点?我试着用 std::function 来做到这一点,但我不知道如何正确地 declare/initialize/call 让它工作。
编辑:
我已经编辑了 FunctionFromB,因为我跳过了一个重要的部分 -> Func 被循环调用了不同的参数。
编辑2:
提供了帮助,我得到的答案是如何使用 C 风格的函数 ptr 执行此操作,但我想让它与 std::function 一起使用。我是那样做的(注意 class B 和枚举是一样的):
class A
{
private:
retType Func1(arg1Type, arg2Type, arg3Type);
retType Func2(arg1Type, arg2Type, arg3Type);
public:
A();
typedef std::function<retType(arg1Type, arg2Type, arg3Type)> funcPtr;
}
int B::FunctionFromB(Enumtype typeB)
{
A* objectA;
A::funcPtr func = nullptr;
switch(type)
{
case Enumtype::typ2:
func = std::bind(&A::Func2, objectA, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3);
break;
case Enumtype::typ2:
default:
func = std::bind(&A::Func1, objectA, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3);
break;
}
for(int i=0; i<whatever; i++)
func(a+i, b+(2*i), c+(3*i));
}
我想,它有效。如果有人在这里发现错误或更好的方法,请告诉我 ;)
你能为 EnumType 使用一个无作用域的枚举吗?
enum Enumtype
{
enumtyp1,
enumtyp2,
enumtypmax
};
如果它是一个选项,编译器会免费为您提供到 int 的转换:enumtyp1 -> 0
、enumtyp2 -> 1
、enumtypmax -> 2
(根据 3.9.2 § 10 枚举器的值或无作用域枚举类型的对象通过以下方式转换为整数
积分提升)
根据 3.9.2 §2 保证这些值 enumerator-list 被声明为常量,并且可以出现在任何需要常量的地方。枚举器定义 with = 为关联的枚举器提供常量表达式指示的值。如果第一个 枚举数没有初始化器,对应常量的值为零。枚举器定义 没有初始值设定项时,为枚举器提供通过增加前一个枚举器的值而获得的值 一个。
enum { a, b, c=0 };
enum { d, e, f=e+2 };
定义a、c、d为0,b、e为1,f为3。
然后您可以在 A 中构建 A 方法的静态数组,并使用应该比开关更简单的直接数组索引:
enum Enumtype
{
enumtyp1,
enumtyp2,
enummax
};
class A
{
private:
typedef retType (__thiscall A::*funcx)(arg1Type,arg2Type,arg3Type);
retType Func1(arg1Type, arg2Type, arg3Type);
retType Func2(arg1Type, arg2Type, arg3Type);
static funcx fp[enummax];
public:
A();
retType Func(Enumtype, arg1Type, arg2Type, arg3Type);
};
class B
{
private:
arg1Type a;
arg2Type b;
arg3Type c;
public:
int FunctionFromB(Enumtype);
};
int B::FunctionFromB(Enumtype x)
{
A* objectA;
for(int i=0; i<whatever; i++)
{
objectA->Func(x, a+i, b+(2*i), c+(3*i));
}
return whatever;
}
retType A::Func(Enumtype x, arg1Type a, arg2Type b, arg3Type c)
{
funcx f = A::fp[x];
return (this->*fp[x])(a, b, c);
}
A::funcx A::fp[enummax] = { &A::Func1, &A::Func2 };
或者,您可以直接在 B::FunctionFromB
中获取一个指针并直接重复调用它:
enum Enumtype
{
enumtyp1,
enumtyp2,
enummax
};
class A
{
public:
typedef retType (__thiscall A::*funcx)(arg1Type,arg2Type,arg3Type);
private:
retType Func1(arg1Type, arg2Type, arg3Type);
retType Func2(arg1Type, arg2Type, arg3Type);
static funcx fp[enummax];
public:
A();
friend class B;
};
class B
{
private:
arg1Type a;
arg2Type b;
arg3Type c;
A::funcx getFunc(Enumtype);
public:
int FunctionFromB(Enumtype);
};
A::funcx B::getFunc(Enumtype x){
return A::fp[x];
}
int B::FunctionFromB(Enumtype x)
{
A* objectA;
A::funcx funcPtr = getFunc(x);
for(int i=0; i<whatever; i++)
{
(objectA->*funcPtr)(a+i, b+(2*i), c+(3*i));
}
return whatever;
}
A::funcx A::fp[enummax] = { &A::Func1, &A::Func2 };
在后一种情况下,您可以避免在 A 中声明方法数组,坚持使用 EnumType 的作用域枚举,并在每次调用 B::FunctionFromB
时使用开关一次:
A::funcx B::getFunc(Enumtype x){
switch (x) {
case EnumType::typ1:
return &A::Func1;
case EnumType::typ2:
return &A::Func2;
case default:
return &A::Func1;
}
}