是否有可能有一个继承最终函数但创建相同函数(而不是覆盖)的派生类?

Posted

技术标签:

【中文标题】是否有可能有一个继承最终函数但创建相同函数(而不是覆盖)的派生类?【英文标题】:Is it possible to have a derived class that inherits a final function but creates the same function (not override)? 【发布时间】:2017-06-22 17:47:12 【问题描述】:

final 函数有问题。我想“停止”类中的多态性,但我仍然想在派生类中生成相同的函数。

类似这样的:

class Base
    protected:
        int _x, _y;
    public:
        Base(int x = 0, int y = 0) : _x(x), _y(y);
        int x() const  return _x; 
        int y() const  return _y; 
        virtual void print()const cout << _x*_y << endl; 
;

class Derived : public Base
    public:
        Derived(int x = 0, int y = 0) : Base(x, y)
        void print()const final  cout << _x*_y / 2.0 << endl;  // final inheritance
;

class NonFinal : public Derived
        void print()const cout << "apparently im not the last..." << endl  
    // here i want a new function. not overriding the final function from Derived class
;

【问题讨论】:

作为一般规则,我会在隐藏继承成员的代码上调用设计错误(覆盖继承的虚函数的明显例外)。我建议在NonFinal 中调用其他方法。如果您发现自己需要这样做,那么您的 OO 设计就很糟糕。 【参考方案1】:

我认为这是一个实验性问题,因为实际上,当您需要“覆盖最终函数”时,您应该重新考虑自己在做什么(听起来很矛盾,不是吗?)。

但是您可以引入一个“虚拟”参数,即void NonFinal::print(int test=0)const,让编译器将成员函数视为不同的。不确定这是否能解决您的“问题”;但至少它引入了一个同名的函数,它仍然可以在不传递参数的情况下调用,并且与DerivedBase的函数分开。

class NonFinal : public Derived
public:
    void print(int test=0)const cout << "apparently im not the last..." << endl; 
;

int main() 

    Base b (10,10);
    Derived d (20,20);
    NonFinal nf;
    Base *bPtr = &d;
    bPtr->print();  // gives 200
    bPtr = &nf; // gives 0
    bPtr->print();
    nf.print(); // gives "apparantly..."

【讨论】:

【参考方案2】:

抱歉,当基类中存在与final 相同名称的函数时,无法在派生类中创建函数。您需要重新考虑您的设计。

问题源于这样一个事实,即派生类中与基类中的函数同名的函数声明被视为试图覆盖 override 关键字是否存在(出于历史原因,我相信)。所以你不能“关闭”覆盖。

这是一个相关的标准报价:

§ 10.3/4 [class.virtual]

如果某个类B 中的一个虚函数fvirt-specifier 标记final 并且在从B 派生的一个类D 中一个函数D::f覆盖B::f,程序格式错误。 [ 例子:

struct B 
   virtual void f() const final;
;
struct D : B 
   void f() const; // error: D::f attempts to override final B::f
;

——结束

【讨论】:

以上是关于是否有可能有一个继承最终函数但创建相同函数(而不是覆盖)的派生类?的主要内容,如果未能解决你的问题,请参考以下文章

将列表对象作为函数参数传递(而不是默认值),是否有任何陷阱?

为啥具有相同名称但不同签名的多个继承函数不会被视为重载函数?

多态与继承

类中的析构函数是否是虚函数

如何继承继承的方法而不是覆盖继承的方法?

Haskell检查函数是不是两次返回相同的值