【问题标题】:Overload of pure virtual function纯虚函数的重载
【发布时间】:2013-03-27 11:55:31
【问题描述】:

我通常将纯虚函数用于我的代码所需的那些方法,以使其正常工作。因此,我创建接口,然后其他用户实现他们的派生类。派生类只有这些虚函数是公共的,而一些额外的方法应该实现为私有的,因为我的代码没有调用它们。 我不知道这是否可以被视为 OOP 的良好实践(是否有任何设计模式?)。 无论如何,我的问题是: 用户可以重载纯虚函数吗?

class Base
{
public:
 Base();
 virtual ~Base();
 virtual void foo(int,double)=0;
};

class Derived:
public Base
{
 private:
  // methods
 public:
 Derived();
 virtual ~Derived();
 virtual void foo(int, double, double); //this doesn't work
 };

解决方案可能是:

 virtual void foo(int,double,double=0)=0;

在基类中,但它非常有限。你有什么想法?

【问题讨论】:

  • 函数重载代表一个不同的API。一个抽象基类代表一个一致的 API。所以不,这没有意义。
  • 你的例子是不是缺少class Derived : Base
  • @nonsensical :对,我刚刚编辑过。谢谢

标签: c++ oop design-patterns overloading pure-virtual


【解决方案1】:

你不能。

假设你有一个Base 指针,指向一个Derived 对象。拥有Base 指针,您只能“访问”Base 的接口(除非您转换为Derived 指针,但这不是您需要的)。

【讨论】:

  • 是的,这是个问题。所以唯一的解决方案是创建一个抽象类而不是接口。不是吗?
  • @Ale - 我不明白你的意思。 c++中interfaceabstract class有什么区别?
  • link,派生类可以比抽象类有更多的功能。相反,接口限制了方法的数量(在我看来)。
【解决方案2】:

重载函数只是一个与另一个同名的函数,但接受一组不同的参数,即它是一个不同的函数。它与一个或多个重载函数是否为虚函数无关。

在您提供的示例中,我相信用户可以重载纯虚拟函数,但只能在覆盖它之后。而且您无法直接从基类访问该函数 - 您需要将基类指针转换为派生类指针。

【讨论】:

    【解决方案3】:

    这两个功能是不同的。后者不会覆盖第一个

    virtual void foo(int,double)=0;
    virtual void foo(int, double, double);
    

    第二个是特定于派生的新虚函数。

    如果你在最后加上override,编译会抱怨你没有覆盖任何东西。这是 c++11 检查。

    virtual void foo(int, double, double) override;
    

    用户可以重写一个纯虚函数来确认使用函数末尾的override来验证。 在您的情况下,只能使用派生指针或类型访问第二个函数。(尽管除非正确覆盖和实现纯虚函数,否则它不能被实例化,直到那时它是一个抽象类)。因此,如果它不打算被派生自Derived 的类进一步覆盖,那么将其设为虚拟是一种开销,因为无论如何它都不会覆盖基本方法。

    【讨论】:

    • 当这个答案出现时,我正在写override。所以这里至少有链接:msdn.microsoft.com/en-us/library/vstudio/jj678987.aspx
    • @Kupto:为什么在示例中,首先 funcC(double =0.0) 覆盖有效,而在第二个代码中无效?
    • @Ale 我刚刚尝试过,如果考虑到 cmets,第一个示例中的 override 关键字似乎是多余的。
    【解决方案4】:

    正如其他人指出的那样,它只是行不通。

    具体来说,这就是发生的事情

     Derived d;
     d.foo(5, 10.0); // Works as expected
    
     Base &b = d; // b is polymorphic
     b.foo(3,10,4); // foo(int, double, double) is not in class Base, hence compile-time resolution fails!
    

    【讨论】:

      【解决方案5】:

      由于函数签名不同,它不会被覆盖。根据覆盖函数的多态规则,函数签名和类型应该相同。

      在这种情况下,这些功能是不同的。 虚拟 void foo(int,double)=0; virtual void foo(int, double, double);

      【讨论】:

        【解决方案6】:

        在基类中重载 foo 不是最简单的解决方案吗?

        class Base
        {
        public:
         Base();
         virtual ~Base();
         virtual void foo(int,double)=0;
         virtual void foo(int,double,double)=0;
        };
        

        【讨论】:

          猜你喜欢
          • 2010-10-01
          • 2019-07-24
          • 2014-07-20
          • 2012-08-27
          • 2020-10-19
          • 2012-03-20
          • 1970-01-01
          • 2013-10-04
          • 2012-01-31
          相关资源
          最近更新 更多