在宏中指定虚拟函数的正确对象和实现
Specify the right object and implementation of a virtual function in a macro
我有一个抽象类DNXServo和继承抽象类的类XL320和AX12A,它们是具体的。我在main中的具体类的每个对象都对应于Arduino Mega上的串行端口,并且我有6个具有唯一id的伺服器,每个串行端口都挂钩。为了清晰起见,在我的代码中,我使用了与宏相关联的每个伺服的ID,例如:
// SERIAL 3- hips - AX12A object
#define HIP_LEFT_FRONT 11
#define HIP_LEFT_MIDDLE 12
#define HIP_LEFT_BACK 13
#define HIP_RIGHT_FRONT 14
#define HIP_RIGHT_MIDDLE 15
#define HIP_RIGHT_BACK 16
// SERIAL 2 - knees - XL320 object
#define KNEE_LEFT_FRONT 17
#define KNEE_LEFT_MIDDLE 18
#define KNEE_LEFT_BACK 19
#define KNEE_RIGHT_FRONT 20
#define KNEE_RIGHT_MIDDLE 21
#define KNEE_RIGHT_BACK 22
etc.
目前我的main是这样的:
void setup(){
// Call constructors
XL320 arms(Serial1, 112500);
XL320 knees(Serial2, 112500);
AX12A hips(Serial3, 112500);
// Write to Servo
int pos=SetGoalPosition(KNEE_LEFT_FRONT, 250);
}
//return pointer to the object associated with the proper Serial
DNXServo* lookUpServo(int ID){
if (ID>=11 && ID<=16) return &hips;
else if (ID>=17 && ID<=22) return &knees;
else return &arms;
}
int SetGoalPosition(int ID, int position){
DNXServo * servo_ptr = lookUpServo(ID);
return servo_ptr->SetGoalPosition(ID,position);
}
SetGoalPosition实际上是DNXServo类中的虚拟成员函数,在XL320和AX12A中有不同的具体实现。这种情况与许多其他成员函数相同。我当前实现的问题是,我必须在main中为每个成员函数定义一个额外的函数。
我可以避免使用宏吗?理想情况下,我想写像
这样的东西SERVO(KNEE_LEFT_FRONT).SetGoalPosition(250);
其中SetGoalPosition是任意成员函数的名称,并自动调用lookUpServo,然后调用该虚函数的正确实现。
EDIT: int XL320::SetGoalPosition(int ID, int position)
是函数的实际定义。注意,它有两个参数。所以我想把SERVO(KNEE_LEFT_FRONT).SetGoalPosition(250);
展开成hips.SetGoalPosition(KNEE_LEFT_FRONT, 250);
这样的东西。正如评论中所建议的,引用也可以工作,但随后我需要始终键入两次ID SERVO(KNEE_LEFT_FRONT).SetGoalPosition(KNEE_LEFT_FRONT, 250);
完全去掉SetGoalPosition(int, int)
。代码调用应该是这样的:
lookupServo(theId)->SetGoalPosition(42);
那么你就解决了"需要为接口中的每个方法创建一个函数"的问题。虽然对我来说似乎没有必要,但上面的宏应该是这个
#define SERVO(theId) (*(lookupServo(theId)))
现在你可以写你想写的SERVO(5).SetGoalPosition(42)
。
另一方面,您可以让lookupServo返回其他人提到的引用:
DNXServo& lookUpServo(int ID) {
if (ID>=11 && ID<=16) return hips;
else if (ID>=17 && ID<=22) return knees;
else return arms;
}
现在你可以用"。"来代替难看的"->",所以我给你的第一行可以稍微改进一下。
lookupServo(theId).SetGoalPosition(42);
注意用点代替"->"。如果需要的话,宏可以更简单一些。
#define SERVO(theId) (lookupServo(theId))
但我想说的是,要么使用我上面展示的第一行代码,并省略SetGoalPosition(int, int)和宏,要么使用使用引用的第二个版本的lookupServo。在这种情况下,不需要返回指针,也没有很好的理由这样做,所以我认为引用版本稍微好一点。
关于将返回指针的函数转换为返回引用的函数的一个小设计注意事项,我想说,您可能喜欢指针返回空指针的能力,但这并不一定是您可以想象的优势(例如,访问冲突)。将一个函数转换为返回一个引用意味着你给自己强加了一个永远不会返回null的契约,这对于表达设计而言可能是一件非常好的事情。在以前您将返回空指针的情况下,问题出现了,您现在应该做什么?答案是在不能返回有效引用时抛出异常。
- 如何实现自定义匹配器以检查 Catch2 中的对象相等性
- 我能否通过将函数实现为类对象方法来避免使用互斥锁
- 为什么地图需要实现'operator<'以及如何比较对象?
- CMake + Qt,moc 编译失败,无法实现 QMetaObject 方法(编译器找不到基本 ui 对象的标头?
- C++接口实现和子类化对象识别
- 对象内部有大量数据容器,实现更高效的对象交换
- 使用初始值设定项列表作为函数参数的类对象实现运算符 [] 的示例
- 可选<double>可以作为 8 字节对象实现吗?
- 我们可以在同一对象中实现多个QtRO接口吗?
- 如何在V8中为C 本机对象实现属性枚举器
- 我真的需要为常量对象实现用户提供的构造函数吗?
- C++对象 [实现] 运算符 == 错误
- 使用指针和使用静态对象实现单例实现之间的区别
- 为具有内部指针的对象实现swap()
- 对象实现后动态绑定大多数不相关的对象
- 此同步对象实现线程是否安全
- 如何在c++中为每个对象实现定时器
- 预序列化消息对象-实现
- 使用ADO命令对象实现批量/批量插入
- 用抽象基类重用对象实现多态