【问题标题】:Overload a virtual method in a derived class so it takes more parameters in C++在派生类中重载虚方法,以便在 C++ 中采用更多参数
【发布时间】:2021-05-10 19:48:15
【问题描述】:

我有一个带有纯虚方法void foo(int a) = 0的抽象类A

然后我有几个继承自A 的类,它们都定义了方法foo。但我需要其中一个 B 来实现它,所以 foo 需要一个额外的参数 int b,所以有点过载。

那我想这样做:

A *bInstance = new B();
bInstance -> foo(1, 2);

但我收到一条错误消息,告诉我foo 采用了太多参数。

在写这篇文章时,我意识到这样做是一件很奇怪的事情,所以也许你不能这样做,但你不能这样做是件好事。但如果可能的话,请告诉我应该怎么做。

【问题讨论】:

  • 你为什么要这个?我的意思是,如果派生类有另一个接口,为什么要使用公共基础?这似乎是设计的味道。

标签: c++ inheritance operator-overloading abstract-class


【解决方案1】:

只有当要使用​​的指针是 B 类型时,才能使用 B 的重载函数。

见:

#include <iostream>
#include <memory>

class A{
public:
  virtual void foo(int a) = 0;
};

class B : public A
{
public:
    virtual void foo(int a) override
    {

    }
    void foo(int a, int b)
    {
        std::cout << a << "," << b;
    }
};

int main(){
    auto b = std::make_shared<B>();
    b->foo(1, 2);
    
    //to use a:
    A* aPtr = b.get();
    aPtr->foo(1);

    return 0;
}

【讨论】:

  • 我明白了,谢谢!这是有道理的,当指针是 A 类型时,编译器会在类 A 中声明 foo 并且只看到 1 个参数
  • 是的,为了进一步继承,您应该添加一个虚拟析构函数。您可能应该使用 std::make_unique 或简单的堆栈分配。
  • 我更喜欢 std::shared_ptr&lt;A&gt; aPtr{b}; 与您自己提出的建议和安全性保持一致 - 提取原始指针并不是很幸运(可能会试图删除它导致段错误)。
【解决方案2】:

虽然 Bernd 的答案是可能的,但您必须问自己过载的影响是什么。例如,考虑以下内容。

std::unique_ptr<A> bAsA = std::make_unique<B>();
bAsA->foo(1, 2); // no worky.
bAsA->foo(1); // works, but what should it do?

如果AB 之间存在不同的接口,我建议以新基类的形式添加一个抽象层(我将其称为C)。

所以不是

struct A {
    // common
    virtual void bar() {}
    // class specific
    virtual void foo(int) = 0;
};

struct B: public A {
    // weird unused override which is still available
    void foo(int) override {}
    // class specific
    void foo(int, int) {}
};

使用

struct C {
    // common
    virtual void bar() {}
};

struct A: public C {
    // class specific
    virtual void foo(int) = 0;
};

struct B: public C {
    // class specific
    void foo(int, int) {}
};

【讨论】:

    【解决方案3】:

    您可以使用默认参数完全实现您想要的:

    class A
    {
        public:
        virtual void foo(int a, int b = 0) = 0;
        virtual ~A() = default;
    };
    
    class B : public A
    {
        public:
        void foo(int a, int b) override { }
    };
    
    class C : public A
    {
        public:
        void foo(int a, int b = 0) override { }
    };
    
    int main()
    {
        A* b = new B();
        A* c = new C();
    
        b->foo(1, 2);
        c->foo(1);
    }
    

    如果您不需要,则不必在 C::foo 实现(以及任何其他派生类)中使用此参数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-17
      • 1970-01-01
      • 2013-05-18
      • 2014-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多