C ++ - 继承中的重载与覆盖
C++ - Overloading vs Overriding in Inheritance
据我所知,覆盖是指当您有 2 个具有相同名称和函数 return 类型(void
、int
、float
的函数时。 . 等)和相同的参数编号和类型。
并且重载是当您有 2 个具有相同名称但参数 number/types 或函数 return 类型应该不同的函数时。
但是今天当我在 class 时,我看到了这张幻灯片:
这不应该超载吗?不压倒一切?因为这里 return 类型发生了变化(从 void
to float
) 和 fa1() 函数在基础 class 中没有参数,但在派生的 class 中它有 float 参数。
如果这是压倒一切的,为什么?
ia1
没有超载。首先你不能重载变量。所以 ia1
绝对是一个覆盖。这也是一件危险的事情。在我的公司,我们的编码标准在任何情况下都不允许覆盖变量名。这只会导致混乱。
fa1
不过——这看起来像是过载。基本 class fa1()
不带参数,但 subclass 版本带浮点数。
在 C++ 中,派生 class 中的任何方法仅在它们的声明匹配时覆盖基 class 中的方法(我说“匹配”但我不知道正式术语那)。也就是说,所有参数必须具有相同的类型,并且 this
的 const
限定必须相同。如果有任何不匹配,派生的 class 中的方法将隐藏 所有具有相同名称的方法,而不是覆盖。这就是您图片中的“错误”试图告诉您的内容。所以 // overrides
在该图片的评论中是不正确且具有误导性的。
是的,很多C++老师其实并不理解这些有些晦涩的细节。
顺便说一句,如果你想覆盖,你的基础class中的方法应该是virtual
;否则,多态性将不起作用。如果不是virtual
,我们也说derived-class方法隐藏了base-class方法。然而,这里关于隐藏的部分几乎没有任何意义;这个词真正想表达的是你没有压倒一切。
此外,正如您所注意到的,重载 存在多个具有相同名称但不同签名的方法。它们都应该出现在派生 class 中才有用——如果派生 class 只有一种方法 fa1
,而其他 fa1
在基础中,它们将被隐藏。但是,有语法糖将所有 fa1
从基础“复制”到派生,禁用所有 hiding 语义:
class A
{
public:
void fa1();
void fa1(int);
};
class B: public A
{
public:
using A::fa1;
void fa1(int, int);
};
...
B b;
b.fa1(); // calls A::fa1()
b.fa1(4); // calls A::fa1(int)
b.fa1(4, 8); // calls B::fa1(int, int)
关于隐藏的部分很少(如果有的话)有用。重写时,你应该告诉你的编译器——为此使用 override
关键字。然后,编译器将检查您的代码是否按预期工作。
class A
{
public:
virtual void fa1(int) {}
void fa2(int) {}
};
class B: public A
{
public:
void fa1(int) override {} // OK
void fa1() override {} // ERROR: doesn't really override - different signature
void fa2(int) override {} // ERROR: doesn't really override - not virtual in base
};
据我所知,覆盖是指当您有 2 个具有相同名称和函数 return 类型(void
、int
、float
的函数时。 . 等)和相同的参数编号和类型。
并且重载是当您有 2 个具有相同名称但参数 number/types 或函数 return 类型应该不同的函数时。
但是今天当我在 class 时,我看到了这张幻灯片:
void
to float
) 和 fa1() 函数在基础 class 中没有参数,但在派生的 class 中它有 float 参数。
如果这是压倒一切的,为什么?
ia1
没有超载。首先你不能重载变量。所以 ia1
绝对是一个覆盖。这也是一件危险的事情。在我的公司,我们的编码标准在任何情况下都不允许覆盖变量名。这只会导致混乱。
fa1
不过——这看起来像是过载。基本 class fa1()
不带参数,但 subclass 版本带浮点数。
在 C++ 中,派生 class 中的任何方法仅在它们的声明匹配时覆盖基 class 中的方法(我说“匹配”但我不知道正式术语那)。也就是说,所有参数必须具有相同的类型,并且 this
的 const
限定必须相同。如果有任何不匹配,派生的 class 中的方法将隐藏 所有具有相同名称的方法,而不是覆盖。这就是您图片中的“错误”试图告诉您的内容。所以 // overrides
在该图片的评论中是不正确且具有误导性的。
是的,很多C++老师其实并不理解这些有些晦涩的细节。
顺便说一句,如果你想覆盖,你的基础class中的方法应该是virtual
;否则,多态性将不起作用。如果不是virtual
,我们也说derived-class方法隐藏了base-class方法。然而,这里关于隐藏的部分几乎没有任何意义;这个词真正想表达的是你没有压倒一切。
此外,正如您所注意到的,重载 存在多个具有相同名称但不同签名的方法。它们都应该出现在派生 class 中才有用——如果派生 class 只有一种方法 fa1
,而其他 fa1
在基础中,它们将被隐藏。但是,有语法糖将所有 fa1
从基础“复制”到派生,禁用所有 hiding 语义:
class A
{
public:
void fa1();
void fa1(int);
};
class B: public A
{
public:
using A::fa1;
void fa1(int, int);
};
...
B b;
b.fa1(); // calls A::fa1()
b.fa1(4); // calls A::fa1(int)
b.fa1(4, 8); // calls B::fa1(int, int)
关于隐藏的部分很少(如果有的话)有用。重写时,你应该告诉你的编译器——为此使用 override
关键字。然后,编译器将检查您的代码是否按预期工作。
class A
{
public:
virtual void fa1(int) {}
void fa2(int) {}
};
class B: public A
{
public:
void fa1(int) override {} // OK
void fa1() override {} // ERROR: doesn't really override - different signature
void fa2(int) override {} // ERROR: doesn't really override - not virtual in base
};