C++ 重载方法重写:是否有任何简化?

C++ 重载方法重写:是否有任何简化?,c++,c++11,overriding,C++,C++11,Overriding,我正在编写一个类的重写,它使用了讨厌的非C++11代码。不幸的是,我不允许更改父类。 它有两个同名的方法,其中一个被子类重写。此外,该方法将作为参数传递给方法。我希望这里有函子,但正如我之前写的,我无法更改CLassA。 简化的代码如下所示: 父类: class CLassA { public: typedef void (CLassA::*Method_t)(int x, int y); int ForAll(Method_t action, int y); virt

我正在编写一个类的重写,它使用了讨厌的非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;
}
输出():

方法A:1 方法A:1 方法A:2 方法A:2 方法A:3 方法A:3 我绝对不喜欢,我必须将名称空间添加到引用和调用中(
ForAll(&CLassC::CLassA::MethodA,x);
B.CLassA::MethodA(2);


您能给我一个提示,如何避免这些丑陋的符号吗?

当您用相同的名称重写两个方法重载中的一个时,会出现某种名称冲突。将第二个方法重命名为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
而不是原始方法指针可以解决此问题。

当您仅重写一个可能的重载方法时,请在子类中添加“using BaseClass::MethodA;”

因此,ClassB声明变成了

class ClassB : public ClassA {
 public:
  using ClassA::MethodA;
  virtual void MethodA(int x, int y) override;
};

你的定义没有改变。然后你可以做
B.MethodA(2)在派生类中声明函数时,基类中具有相同名称的任何重载都将隐藏。无论函数是重载还是重写,此规则都适用。当具有重载的
虚拟
函数时,尤其是当它们具有实现时,通常的做法是具有调用
受保护的
函数的
公共
和非
虚拟
转发函数。这样就可以在不影响调用接口的情况下单独重写
虚拟
函数。请参见示例
std::num\u get

当您在基类中重载了
virtual
函数时,您无法更改最佳方法是使用
声明使基类重载可见:

class CLassB: public CLassA {
public:
    using CLassA::MethodA;
    void MethodA(int, int) override;
};

我可能弄错了,但我不认为
CLassC::CLassA::MethodA
中的
CLassC::
实际上是必需的
CLassA
似乎是
CLassC
中一个明确的标识符。另外,应该提到的是,因为
CLassB
MethodA
的定义是非虚拟的,如果您有一个
CLassC
当前被标识为
CLassB
CLassA
(例如在
CLassB
或诸如此类的向量中),它将调用
CLassB
版本的
MethodA
而不是
CLassC
版本。我不确定这是否是有意的。你能给我们一点关于你实际尝试做什么的详细信息吗?例如,如果你正在调用
B.CLassA::MethodA(2)
你还会调用
B.MethodA
吗?如果不会,为什么要
CLassB
重写
MethodA
,如果是这样,为什么不创建一个
MethodB
为你调用
CLassA::MethodA
CLassB::MethodA
(否则,
override
说明符将导致错误),我添加了显示它的输出。顺便说一句,使用警告选项
-Woverloaded virtual
GCC会发出警告,指出某些虚拟函数被重写隐藏
class CLassB: public CLassA {
public:
    using CLassA::MethodA;
    void MethodA(int, int) override;
};