C++ 用不同方法的签名覆盖理解
C++ override understanding with different method's signatures
我希望在 C++ 中,如果方法在 Base 和 Derived classes 中具有相同的签名,包括名称、参数和 return 类型,那么您可以覆盖方法。
如果我尝试编译这样的东西,我会在两种方法(get、get2)上都失败:
#include <iostream>
class A
{
public:
A() {}
virtual int get() { return 0; }
virtual int *get2() { return 0; }
};
class B : public A
{
public:
B() {}
float get() override { return 0.f; }
float *get2() override { return 0.f; }
};
using namespace std;
int main()
{
A a;
B b;
cout << a.get() << endl;
cout << b.get() << endl;
return 0;
}
我有代码:
#include <iostream>
class C
{
public:
C(){};
virtual int get() { return 0; };
};
class D : public C
{
public:
D(){};
int get() override { return 1; };
};
class E : public D
{
public:
E(){};
virtual int get() { return 2; };
};
class A
{
public:
A() { d = new D(); }
virtual D *get() { return dynamic_cast< D * >(d); }
D *d;
};
class B : public A
{
public:
B() { d = new E(); }
E *get() override { return dynamic_cast< E * >(d); }
};
class Z : public A
{
public:
Z() { d = new E(); }
C *get() override { return dynamic_cast< C * >(d); }
};
using namespace std;
int main()
{
A a;
B b;
Z z;
cout << a.get()->get() << endl;
cout << b.get()->get() << endl;
cout << z.get()->get() << endl;
return 0;
}
而且我预计 classes(B 和 Z)都会失败。但是我只在 class Z 上失败了。有人可以解释一下吗?
如果基 class 声明了一个 return 是指向 class 的指针或引用的虚函数,则重写虚函数 可以 return 指向 class 类型的指针或引用,派生自基函数声明的 return 类型。
这被称为“协变 return 类型”。
示例:
class Object {};
class Derived : public Object {};
class Interface {
public:
virtual Object* get() = 0;
};
class Impl : public Interface {
public:
Derived* get() override { return nullptr; } // OK
};
如果你有一个指向接口的指针并调用 get(),你会得到一个 Object*,因为 Derived* 由于继承可以转换为 Object*。
但是,如果您有一个 Impl 实例,并且直接在其上调用 get()
,则可以受益于更具体的 return 类型。 (毕竟,如果您使用的是 impl 类型而不是其接口,那么了解更多关于实现的信息不是问题。)
按照标准:
[class.virtual] 11.6.2.8:
The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. If a function D::f overrides a function B::f, the return types of the functions are covariant if they satisfy the following criteria:
- both are pointers to classes, both are lvalue references to classes, or both are rvalue references to classes
- the class in the return type of B::f is the same class as the class in the return type of D::f, or is an unambiguous and accessible direct or indirect base class of the class in the return type of D::f
- both pointers or references have the same cv-qualification and the class type in the return type of D::f has the same cv-qualification as or less cv-qualification than the class type in the return type of B::f.
我希望在 C++ 中,如果方法在 Base 和 Derived classes 中具有相同的签名,包括名称、参数和 return 类型,那么您可以覆盖方法。
如果我尝试编译这样的东西,我会在两种方法(get、get2)上都失败:
#include <iostream>
class A
{
public:
A() {}
virtual int get() { return 0; }
virtual int *get2() { return 0; }
};
class B : public A
{
public:
B() {}
float get() override { return 0.f; }
float *get2() override { return 0.f; }
};
using namespace std;
int main()
{
A a;
B b;
cout << a.get() << endl;
cout << b.get() << endl;
return 0;
}
我有代码:
#include <iostream>
class C
{
public:
C(){};
virtual int get() { return 0; };
};
class D : public C
{
public:
D(){};
int get() override { return 1; };
};
class E : public D
{
public:
E(){};
virtual int get() { return 2; };
};
class A
{
public:
A() { d = new D(); }
virtual D *get() { return dynamic_cast< D * >(d); }
D *d;
};
class B : public A
{
public:
B() { d = new E(); }
E *get() override { return dynamic_cast< E * >(d); }
};
class Z : public A
{
public:
Z() { d = new E(); }
C *get() override { return dynamic_cast< C * >(d); }
};
using namespace std;
int main()
{
A a;
B b;
Z z;
cout << a.get()->get() << endl;
cout << b.get()->get() << endl;
cout << z.get()->get() << endl;
return 0;
}
而且我预计 classes(B 和 Z)都会失败。但是我只在 class Z 上失败了。有人可以解释一下吗?
如果基 class 声明了一个 return 是指向 class 的指针或引用的虚函数,则重写虚函数 可以 return 指向 class 类型的指针或引用,派生自基函数声明的 return 类型。
这被称为“协变 return 类型”。
示例:
class Object {};
class Derived : public Object {};
class Interface {
public:
virtual Object* get() = 0;
};
class Impl : public Interface {
public:
Derived* get() override { return nullptr; } // OK
};
如果你有一个指向接口的指针并调用 get(),你会得到一个 Object*,因为 Derived* 由于继承可以转换为 Object*。
但是,如果您有一个 Impl 实例,并且直接在其上调用 get()
,则可以受益于更具体的 return 类型。 (毕竟,如果您使用的是 impl 类型而不是其接口,那么了解更多关于实现的信息不是问题。)
按照标准:
[class.virtual] 11.6.2.8: The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. If a function D::f overrides a function B::f, the return types of the functions are covariant if they satisfy the following criteria:
- both are pointers to classes, both are lvalue references to classes, or both are rvalue references to classes
- the class in the return type of B::f is the same class as the class in the return type of D::f, or is an unambiguous and accessible direct or indirect base class of the class in the return type of D::f
- both pointers or references have the same cv-qualification and the class type in the return type of D::f has the same cv-qualification as or less cv-qualification than the class type in the return type of B::f.