简体   繁体   English

C ++函数覆盖

[英]C++ function overriding

I have three different base classes: 我有三个不同的基类:

class BaseA
{
public:
    virtual int foo() = 0;
};

class BaseB
{
public:
    virtual int foo() { return 42; }
};

class BaseC
{
public:
    int foo() { return 42; }
};

I then derive from the base like this (substitute X for A, B or C): 然后我从这个基础派生出来(用A替代A,B或C):

class Child : public BaseX
{
public:
    int foo() { return 42; }
};

How is the function overridden in the three different base classes? 如何在三个不同的基类中重写该函数? Are my three following assumptions correct? 我的以下三个假设是否正确? Are there any other caveats? 还有其他警告吗?

  • With BaseA, the child class doesn't compile, the pure virtual function isn't defined. 使用BaseA,子类不编译,未定义纯虚函数。
  • With BaseB, the function in the child is called when calling foo on a BaseB* or Child*. 使用BaseB,在BaseB *或Child *上调用foo时会调用子函数。
  • With BaseC, the function in the child is called when calling foo on Child* but not on BaseB* (the function in parent class is called). 使用BaseC时,在Child *上调用foo但在BaseB *上调用foo时调用子函数(调用父类中的函数)。

The important rule to remember is once a function is declared virtual, functions with matching signatures in the derived classes are always virtual. 要记住的重要规则是,一旦函数声明为虚拟,派生类中具有匹配签名的函数始终是虚拟的。 So, it is overridden for Child of A and Child of B, which would behave identically (with the exception of you can't directly instantiate BaseA). 因此,它被重写为A的Child和B的Child,它的行为相同(除了你不能直接实例化BaseA)。

With C, however, the function isn't overridden, but overloaded. 但是,使用C,函数不会被覆盖,而是会被重载。 In that situation, only the static type matters: it will call it on what it is a pointer to (the static type) instead of what the object really is (the dynamic type) 在那种情况下,只有静态类型很重要:它会调用它的指针(静态类型)而不是对象的真实类型(动态类型)

In the derived class a method is virtual if it is defined virtual in the base class, even if the keyword virtual is not used in the derived class's method. 在派生类中,如果在基类中定义了虚拟方法,则该方法是虚拟的,即使在派生类的方法中未使用关键字virtual也是如此。

  • With BaseA , it will compile and execute as intended, with foo() being virtual and executing in class Child . 使用BaseA ,它将按预期编译和执行, foo()是虚拟的并在类Child执行。
  • Same with BaseB , it will also compile and execute as intended, with foo() being virtual() and executing in class Child . BaseB相同,它也将按预期编译和执行, foo()为virtual()并在类Child执行。
  • With BaseC however, it will compile and execute, but it will execute the BaseC version if you call it from the context of BaseC , and the Child version if you call with the context of Child . 随着BaseC但是,它将编译并执行,但它将执行BaseC如果你从上下文中调用它的版本BaseCChild的版本,如果你用的情况下呼叫Child

With BaseA, the child class doesn't compile, the pure virtual function isn't defined 使用BaseA,子类不编译,未定义纯虚函数

This is true only if you try to create an object of BaseA. 仅当您尝试创建BaseA对象时才会出现这种情况。 If you create a object of Child and then you can call foo() using either BaseA* or Child* 如果你创建一个Child对象,那么你可以使用BaseA *或Child *调用foo()

With BaseB, the function in the child is called when calling foo on a BaseB* or Child*. 使用BaseB,在BaseB *或Child *上调用foo时会调用子函数。

Depends upon the type of the object as the object can be either BaseB or Child. 取决于对象的类型,因为对象可以是BaseB或Child。 If the object is BaseB then BaseB::foo is called. 如果对象是BaseB,则调用BaseB :: foo。

With BaseC, thefunction in the child is called when calling foo on Child* but not on BaseB* (the function in parent class is called). 使用BaseC时,在Child *上调用foo时调用子函数,但在BaseB *上调用foo(调用父类中的函数)。

Yes, but you never want to do this. 是的,但你永远不想这样做。

From a polymorphism point of view, prefer A, so you know each child has his own implementation of the virtual function. 从多态性的角度来看,更喜欢A,所以你知道每个孩子都有自己的虚函数实现。
Choose B mainly if you have a valid default implementation, but then you have to make sure that all child-classes have their own implementation as needed. 如果您具有有效的默认实现,则主要选择B,但是您必须确保所有子类都根据需要具有自己的实现。 C is not polymorphism, so use judiciously. C不是多态,所以明智地使用。

It mostly depends on how you called it. 这主要取决于你如何称呼它。

if you did: 如果你这样做:

class Child : public BaseA
{
public:
    int foo() { return 42; }
};

and did 并做到了

BaseA baseA = new Child();
baseA->foo();

It would call Child's foo function. 它会调用Child的foo函数。

However, if you did this: 但是,如果你这样做:

BaseA baseA = new BaseA();

It would produce a compile time error. 它会产生编译时错误。

Class Child will compile if derived from A, you just can't instantiate objects of that type. 如果派生自A,则类Child 编译,您无法实例化该类型的对象。

This might be valuable if you were going to override some functions from Base, and then derive again. 如果您要从Base覆盖某些函数,然后再次派生,这可能很有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM