重载方法覆盖:有任何简化吗?

时间:2013-11-18 08:47:27

标签: c++ c++11 override

我正在编写一个类的覆盖,它使用令人讨厌的非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);)。

请你给我一个提示,如何避免这些丑陋的记谱?

3 个答案:

答案 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来消除歧义。