我正在编写一个类的覆盖,它使用令人讨厌的非C ++ 11代码。不幸的是,我不允许更改父类。 它有两个具有相同名称的方法,其中一个被子类重写。此方法也作为参数传递给方法。我想在这里有仿函数,但正如我之前写的那样,我无法改变CLassA。 简化代码如下所示:
家长班:
class CLassA
{
public:
typedef void (CLassA::*Method_t)(int x, int y);
int ForAll(Method_t action, int y);
virtual void MethodA(int x);
virtual void MethodA(int x, int y);
};
int CLassA::ForAll(Method_t action, int x)
{
(this->*action)(x, x);
return x;
}
void CLassA::MethodA(int x)
{
printf("CLassA::MethodA: %d\n", x);
ForAll(&CLassA::MethodA, x);
}
void CLassA::MethodA(int x, int y)
{
printf("\tCLassA::MethodA: %d %d\n", x, y);
}
我的第一次覆盖:
class CLassB : public CLassA
{
public:
void MethodA(int x, int y) override;
};
void CLassB::MethodA(int x, int y)
{
printf("\tCLassB::MethodA: %d %d\n", x, y);
}
我的第二次覆盖:
class CLassC : public CLassB
{
public:
void MethodA(int x) override;
};
void CLassC::MethodA(int x)
{
printf("CLassC::MethodA: %d\n", x);
ForAll(&CLassC::CLassA::MethodA, x);
}
调用例程:
int main(int argc, char** argv)
{
CLassA A;
A.MethodA(1);
CLassB B;
B.CLassA::MethodA(2);
CLassC C;
C.MethodA(3);
return 0;
}
输出(link):
CLassA::MethodA: 1 CLassA::MethodA: 1 1 CLassA::MethodA: 2 CLassB::MethodA: 2 2 CLassC::MethodA: 3 CLassB::MethodA: 3 3
我绝对不喜欢,我必须在引用中添加名称空间并调用(ForAll(&CLassC::CLassA::MethodA, x);
,B.CLassA::MethodA(2);
)。
请你给我一个提示,如何避免这些丑陋的记谱?
答案 0 :(得分:1)
在派生类中声明函数时,将隐藏基类中具有相同名称的任何重载。无论函数是重载还是覆盖,此规则都适用。当重载virtual
函数时,尤其是当它们具有实现时,正常的附加操作是具有调用public
函数的virtual
和非protected
转发函数。这样,可以单独覆盖virtual
函数,而不会影响调用接口。请参阅示例std::num_get<...>
。
当您在基类中重载virtual
函数时,无法更改最佳方法是使用using
声明使基类重载可见:
class CLassB: public CLassA {
public:
using CLassA::MethodA;
void MethodA(int, int) override;
};
答案 1 :(得分:0)
当您使用相同名称覆盖两个方法重载之一时,会出现某种名称冲突。将第二种方法重命名为MethodB可以解决您的B.ClassA::MethodA(2)
问题:
class CLassA
{
public:
typedef void (CLassA::*Method_t)(int x, int y);
int ForAll(Method_t action, int y);
virtual void MethodA(int x);
virtual void MethodB(int x, int y);
};
对于ForAll(&CLassC::CLassA::MethodA, x);
,这只是类型推断的问题。
要么你应该施展它:
void CLassC::MethodA(int x)
{
printf("CLassC::MethodA: %d\n", x);
ForAll((Method_t)&CLassC::MethodB, x);
}
或者使用std::function
而不是原始方法指针应该解决这个问题。
答案 2 :(得分:0)
如果您只覆盖其中一个潜在的重载方法,请添加“using BaseClass :: MethodA;”给你的孩子上课。
所以,ClassB声明变成了;
class ClassB : public ClassA {
public:
using ClassA::MethodA;
virtual void MethodA(int x, int y) override;
};
并且您的定义不会改变。然后你可以做B.MethodA(2);
而无需坚持使用中间的ClassA来消除歧义。