函数参数的继承

函数参数的继承

问题描述:

我想知道如何正确地重写派生类与派生函数参数的功能?
例如函数参数的继承

struct X; 
struct Y:X 
struct Z:X 

class A { 
    public: 
     int f(int, X);  
}; 

class B : A{ 
    public: 
     int f(int, Y); 
}; 

class C : A{ 
    public: 
     int f(int, Z); 
}; 
+0

如果可能,请考虑将X传递给动态类型为B的A,该呼叫应该解析为什么? –

+0

你不能这样做,因为它会是错的。不支持反方差,仅支持返回类型的协方差。 – Jarod42

+0

@ Jarod42,但只有返回参考和指针和基准派生关系的协方差,它是协方差的一个子阵。 – Yakk

您可以使用返回值/参数的派生/基类的基数称为协变返回类型和逆变参数。

在C++中,virtual指针的引用和指针返回类型在派生类型中具有协变重载;您可以在派生类型中返回一个更受限制的(指针或引用)到基类返回类型。

在C++中不支持参数变异,其中基本接口中的参数Derived*替换为派生参数中的Base*参数,但您可以通过重载和重写来模拟它。

struct BaseValue {}; 
struct DerivedValue:BaseValue {}; 
struct MoreDerivedValue:DerivedValue {}; 

struct BaseInterface { 
    virtual void contra_example(DerivedValue* ptr) = 0; 
    virtual DerivedValue* co_example() = 0; 
    virtual ~BaseInterface() {} 
}; 

struct DerivedInterface:BaseInterface { 
    virtual void contra_example(DerivedValue* ptr) override final { 
    contra_example(static_cast<Value*>(ptr)); 
    } 
    void contra_example(Value* ptr) override = 0; 

    virtual MoreDerivedValue* co_example() override = 0; 
}; 

co_example是返回类型中的协方差的一个例子。编译器会自动为我们做这个事情,在这种情况下,我们只是基于指针和引用类型heirarchy来做协方差。

contra_example是参数类型的反例的例子。 ptr,参数为contra_example,在DerivedInterface的情况下可以是任何Value*。基本接口要求它是一个DerivedValue*

我们都可以覆盖基本contra_example,然后转发给内部“比较能接受”的实施是一个超载DerivedInterface

派生接口是更宽容比基部接口,它提供了保证至少一样好,或者比原来的不更好


现在让我们回到你的问题。首先,不,编译器不会为你做。

其次,你的逻辑是有缺陷的。使用Liskov substitution principle,您的B必须能够代替A

但你B更受限制合同上的参数fA一样。 A需要X自变量,B要求它不仅是X而且还有Y

struct X1{}; 
struct X2{}; 
struct Y:X1,X2{}; 

struct A { 
    virtual void foo(Y*) = 0; 
    virtual ~A() {} 
} 
struct B1:A { 
    virtual void foo(Y* ptr) final override { foo(static_cast<X1*>(ptr)); } 
    virtual void foo(X1*) = 0; 
} 
struct B2:A { 
    virtual void foo(Y* ptr) final override { foo(static_cast<X2*>(ptr)); } 
    virtual void foo(X2*) = 0; 
} 

这对应于您的示例。派生的接口更容许他们的(隐式输入)参数。

你可以跳过这个循环以获得支持协方差的只出错的参数,或者直接返回它们。