虚拟成员函数的目的是什么?

发布于 2024-08-20 19:08:18 字数 92 浏览 13 评论 0原文

C++ 中函数重写和虚函数之间有什么区别?

虚拟成员函数可以在派生类中重写。 在派生类中重新定义函数称为函数重写。

为什么我们实际上有虚函数?

What is the difference member between function overriding and virtual functions in C++?

Virtual member functions can be overridden in derived classes.
Redefining a function in a derived class is called function overriding.

Why do we actually have virtual functions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

往事风中埋 2024-08-27 19:08:18

虚函数/方法只是一个函数,通过重新定义函数的工作方式(使用相同的签名),可以在子类(或 C++ 术语中的派生类)中重写其行为。

想象一下具有说话功能的基础类哺乳动物。该功能是空的,只是计算哺乳动物如何说话。当你继承这个类时,你可以重写speak方法,这样狗就会发出“Arf Arf!”的声音。猫会“喵喵”地叫。

你的问题似乎是在问有什么区别,其实没有什么区别,因为使用虚函数可以覆盖这些函数的行为。您可能想了解重写函数和重载函数之间的区别。

重载函数意味着创建一个具有相同名称但不同参数(即不同数量和类型的参数)的函数。以下是来自 IBM 网站

重载(仅限 C++)如果您为一个对象指定多个定义
函数名或同一范围内的运算符,您已重载
该函数名称或运算符。重载的函数和运算符是
重载函数(仅限 C++)和重载中描述
分别是运算符(仅限 C++)。

重载声明是用以下方式声明的声明
与先前在同一范围内声明的声明具有相同的名称,
只是两个声明具有不同的类型。

如果调用重载的函数名或运算符,编译器
通过比较来确定要使用的最合适的定义
用于调用函数或运算符的参数类型
定义中指定的参数类型。选择的过程
调用最合适的重载函数或运算符
重载解析,如重载解析(仅限 C++)中所述。

至于需要虚拟函数的情况的完全理性原因,这篇博文给出了一个很好的理由:http://nrecursions.blogspot.in/2015/06/so-why-do-we-need-virtual-functions.html

Virtual function / method is simply a function whose behavior can be overriden within a subclass (or in C++ terms a derived class) by redefining how the function works (using the same signature).

Think of a base class mammal with a speak function. The function is void and simply couts how a mammal speaks. When you inherit from this class you can override the speak method so that dogs go "Arf Arf!" and cats go "Meow Meow".

Your question seems to ask what are the differences, well there are none because with virtual functions one can override the behavior of these functions. You may be after the difference between overriding functions and overloading them.

Overloading functions means to create a function with the same name but different arguments i.e. different number- and type-of argument(s). Here is an explanation on overloading in C++ from IBM's site:

Overloading (C++ only) If you specify more than one definition for a
function name or an operator in the same scope, you have overloaded
that function name or operator. Overloaded functions and operators are
described in Overloading functions (C++ only) and Overloading
operators (C++ only), respectively.

An overloaded declaration is a declaration that had been declared with
the same name as a previously declared declaration in the same scope,
except that both declarations have different types.

If you call an overloaded function name or operator, the compiler
determines the most appropriate definition to use by comparing the
argument types you used to call the function or operator with the
parameter types specified in the definitions. The process of selecting
the most appropriate overloaded function or operator is called
overload resolution, as described in Overload resolution (C++ only).

As for the full rational reason for situations where virtual functions are required, this blog post gives a good one: http://nrecursions.blogspot.in/2015/06/so-why-do-we-need-virtual-functions.html

铃予 2024-08-27 19:08:18

对于多态性,函数重写和虚拟函数之间的区别变得很重要。特别是在使用指向基类的引用或指针时。

基本设置

在 C++ 中,任何派生类都可以传递给需要基类对象的函数。 (另请参阅切片< /a> 和 LSP)。给定:

struct Base_Virtual
{
  virtual void some_virtual_function();
};

struct Base_Nonvirtual
{
  void some_function();
};

void Function_A(Base_Virtual * p_virtual_base);
void Function_B(Base_Nonvirtual * p_non_virtual_base);

在上面的代码中,有两个基类,一个声明了虚方法,另一个声明了非虚函数。

声明了两个需要指向各自基类的指针的函数。

派生类

现在让我们测试多态性,尤其是虚拟与非虚拟(覆盖方法)。
结构:

struct Derived_From_Virtual
: public Base_Virtual
{
  void some_virtual_function(); // overrides Base_Virtual::some_virtual_function()
};

struct Derived_From_Nonvirtual
:公共基础_非虚拟
{
无效一些_函数();
根据

C++ 语言,我可以将指向 Derived_From_Virtual 的指针传递给 Function_A,因为 Derived_From_Virtual 继承自 Base_Virtual 。我还可以将 Derived_From_Nonvirtual 的指针传递给 Function_B

virtual 和重写之间的区别

Base_Virtual 中的 virtual 修饰符告诉编译器 Function_A 将使用 Derived_From_Virtual::some_virtual_function() 而不是 Base_Virtual 中的方法。这是因为该方法是虚拟,最终定义可能驻留在未来派生类中。实际的定义表示在包含该定义的最派生类中使用该方法。

当将 Derived_From_Nonvirtual 的指针传递给 Function_B 时,编译器将指示函数使用基类的方法 Base_Nonvirtual::some_function()。派生类中的 some_function() 方法是与基类独立的、不相关的方法。

虚拟和重写之间的主要区别在于多态性。

The difference between function overriding and virtual function becomes important with polymorphism. Specifically when using references or pointers to a base class.

The Base Setup

In C++, any derived class can be passed to a function requiring a base class object. (See also Slicing and LSP). Given:

struct Base_Virtual
{
  virtual void some_virtual_function();
};

struct Base_Nonvirtual
{
  void some_function();
};

void Function_A(Base_Virtual * p_virtual_base);
void Function_B(Base_Nonvirtual * p_non_virtual_base);

In the above code, there are two base classes, one declares a virtual method, the other declares a non-virtual function.

Two functions are declared that require pointers to the respective base clases.

The Derived Classes

Let us now test the polymorphism, especially virtual vs. non-virtual (overriding methods).
The structures:

struct Derived_From_Virtual
: public Base_Virtual
{
  void some_virtual_function(); // overrides Base_Virtual::some_virtual_function()
};

struct Derived_From_Nonvirtual
: public Base_Nonvirtual
{
void some_function();
}

According to the C++ language, I can pass a pointer to a Derived_From_Virtual to Function_A because Derived_From_Virtual inherits from Base_Virtual. I can also pass a pointer to Derived_From_Nonvirtual to Function_B.

The Difference Between virtual and overriding

The virtual modifier in Base_Virtual, tells the compiler that Function_A will use Derived_From_Virtual::some_virtual_function() instead of the method in Base_Virtual. This is because the method is virtual, the final definition may reside in a future or derived class. The actual definition says to use the method in the most derived class containing the definition.

When passing a pointer to Derived_From_Nonvirtual to Function_B, the compiler will instruct the function to use the method of the base class, Base_Nonvirtual::some_function(). The some_function() method in the derived class is a separate, unrelated, method from the base class.

The primary difference between virtual and overriding occurs with polymorphism.

溇涏 2024-08-27 19:08:18

查看 C++ FAQ lite,http://www.parashift.com/c++-faq-lite/ 。可能是初学者最好的 C++ 资源之一。它有关于虚拟函数和重写的深入文章。

我个人发现 C++ FAQ 是我学习 C++ 的一个很好的资源。其他人有不同的看法,你的里程可能会有所不同

Check out C++ FAQ lite, http://www.parashift.com/c++-faq-lite/. is probably one of the best C++ resources for beginners. it has in-depth write-up about virtual functions and overriding.

I personally found C++ FAQ to be an excellent source as I learn C++. Other people have different opinion, your mileage may vary

别把无礼当个性 2024-08-27 19:08:18

这更多的是对这个答案 而不是答案本身。

virtual 是一个关键字,它请求正在声明的方法的运行时分派,同时将该方法声明为覆盖之一(除了实现的纯虚拟方法)。所声明的方法以及从此类向下的派生层次结构中共享确切签名和名称的任何方法都是覆盖。当您通过父指针或引用调用虚拟方法时,运行时将调用被调用对象的层次结构中最派生的覆盖。

当方法不是虚拟的,并且稍后在层次结构中定义相同的方法时,您将隐藏父方法。这里的区别在于,当通过基指针或引用调用该方法时,它将调用基实现,而如果在派生对象中调用该方法,它将调用派生实现。除其他情况外,这被称为隐藏,因为基函数和派生函数是不相关的,并且在派生类中定义它将会在调用中隐藏基版本:

struct base {
   virtual void override() { std::cout << "base::override" << std::endl; }
   void not_override() { std::cout << "base::not_override" << std::endl; }
};
struct derived : base {
   void override() { std::cout << "derived::override" << std::endl; }
   void not_override() { std::cout << "derived::not_override" << std::endl; }
};
int main() {
   derived d;
   base & b = d;

   b.override();     // derived::override
   b.not_override(); // base::not_override
   d.not_override(); // derived::not_override
}

差异以及错误之处@erik2red 的答案是,覆盖与虚拟函数密切相关,并且意味着存在一个运行时调度机制来确定要调用的最派生覆盖。答案中显示的与覆盖相关的行为实际上是没有覆盖而是方法隐藏时的行为。

其他问题

该语言允许使用纯虚拟方法来实现。它没有说明应该使用什么术语,但是纯虚方法永远不会被考虑用于运行时分派。原因是,当具有纯虚方法(即使已实现)的类被视为抽象类时,您无法实例化该类的对象。一旦您拥有为该方法提供实现的派生类,该实现就成为层次结构中的最终重写。现在可以实例化该类,但不会通过运行时调度机制调用纯虚方法。

如果使用完全限定名称,则可以调用非最终重写的虚拟方法以及隐藏方法。对于虚拟方法,使用完全限定名称会禁用调用的多态调度机制:d.base::override() 将调用基本实现,即使存在其他覆盖 在派生类中。

即使签名不匹配,方法也可以隐藏基类中的其他方法。

struct base {
   void f() {}
};
struct derived : base {
   void f(int) {}
};
int main() {
   derived d;
   // d.f() // error, derived::f requires an argument, base::f is hidden in this context
}

覆盖一样,d.base::f() 将调用基本版本,不是因为它禁用了多态性 - 事实并非如此,因为该方法未声明为虚拟它永远不会有多态行为——而是因为完整的限定告诉编译器该方法在哪里,即使它被派生类中的另一个方法隐藏了。

This is more a follow up on the comments from this answer than an answer by itself.

virtual is a keyword that requests runtime dispatch for the method being declared and at the same time declares the method as one of the overrides (implemented pure virtual methods aside). The method being declared, and any method that shares the exact signature and name in the deriving hierarchy from this class down are overrides. When you call a virtual method through a parent pointer or reference, the runtime will call the most derived override in the hierarchy of the called upon object.

When a method is not virtual, and the same method is defined later on in the hierarchy, you are hiding the parent method. The difference here is that when the method is being called through a base pointer or reference it will be calling the base implementation, while if it is being called in a derived object it will call the derived implementation. This, among other cases, is called hiding because the base and derived functions are unrelated, and having it defined in the derived class will hide the base version from a call:

struct base {
   virtual void override() { std::cout << "base::override" << std::endl; }
   void not_override() { std::cout << "base::not_override" << std::endl; }
};
struct derived : base {
   void override() { std::cout << "derived::override" << std::endl; }
   void not_override() { std::cout << "derived::not_override" << std::endl; }
};
int main() {
   derived d;
   base & b = d;

   b.override();     // derived::override
   b.not_override(); // base::not_override
   d.not_override(); // derived::not_override
}

The difference, and what is wrong in the answer by @erik2red is that overrides are intimately related to virtual functions and imply that there is a runtime dispatch mechanism in place that determines the most derived override to call. The behavior that is shown in the answer and associated to override is actually the behavior when there are no overrides but rather method hiding.

Other issues

The language allows for pure virtual methods with implementation. It does not say anything about what terminology should be used with them, but a pure virtual method will never be considered for runtime dispatch. The reason is that when a classes with pure virtual methods (even if implemented) are considered abstract classes, and you cannot instantiate an object of the class. Once you have a derived class that provides an implementation for that method, that implementation becomes the final override in the hierarchy. The class can now be instantiated, but the pure virtual method will not be called through the runtime dispatch mechanism.

Virtual methods that are not the final override, as well as hided methods can be called if using the fully qualified name. In the case of virtual methods, using the fully qualified name disables the polymorphic dispatch mechanism for the call: d.base::override() will call the base implementation even if there are other overrides in deriving classes.

A method can hide other methods in base classes even if the signatures do not match.

struct base {
   void f() {}
};
struct derived : base {
   void f(int) {}
};
int main() {
   derived d;
   // d.f() // error, derived::f requires an argument, base::f is hidden in this context
}

As with overrides, d.base::f() will call the base version, not because it disables polymorphism --it does not, as the method is not declared virtual it will never have polymorphic behavior-- but because the full qualification tells the compiler where the method is, even if it was hidden by another method in the derived class.

仙女山的月亮 2024-08-27 19:08:18

摘要

在本文中,我们讨论 C++ 中的虚函数。第零部分解释了如何声明和重写虚函数。第一部分尝试(可能失败)解释虚拟函数是如何实现的。第二部分是一个示例程序,它使用第 0 部分和第 1 部分中定义的示例类。第三部分是每个虚函数中给出的经典动物例子——多态性教程。

第零部分

当且仅当其声明如此时,类的方法才被称为虚拟

class my_base
{
public:
            void non_virtual_test() { cout << 4 << endl; } // non-virtual
    virtual void virtual_test()     { cout << 5 << endl; } // virtual
};

(当然,我假设程序员以前没有做过类似#define virtual之类的事情。)

重新声明并重新实现其基类之一的非虚拟方法的类被称为重载该方法。重新声明并重新实现其基之一的虚拟方法的类被称为覆盖该方法。

class my_derived : public my_base
{
public:
    void non_virtual_test() { cout << 6 << endl; } // overloaded
    void virtual_test()     { cout << 7 << endl; } // overriden
};

第一部分

当编译器检测到某个类有虚方法时,它会自动向该类添加一个虚方法表(也称为vtable)内存布局。结果与编译此代码生成的结果类似:

class my_base
{
//<vtable>
// The vtable is actually a bunch of member function pointers
protected:
    void (my_base::*virtual_test_ptr)();
//</vtable>

// The actual implementation of the virtual function
// is hidden from the rest of the program.
private:
    void virtual_test_impl() { cout << 5 << endl; }

// Initializing the real_virtual_test pointer in the vtable.
public:
    my_base() : virtual_test_ptr(&my_base::virtual_test_impl) {}

public:
    void non_virtual_test() { cout << 4 << endl; }
    // The interface of the virtual function is a wrapper
    // around the member function pointer.
    inline void virtual_test() { *virtual_test_ptr(); }
};

当编译器检测到类已重写虚拟方法时,它会替换 vtable 中与其关联的条目。结果类似于编译此代码生成的结果:

class my_derived : public my_base
{
// The actual implementation of the virtual function
// is hidden from the rest of the program.
private:
    void virtual_test_impl() { cout << 7 << endl; }

// Initializing the real_virtual_test pointer in the vtable.
public:
    my_derived() : virtual_test_ptr(&my_derived::virtual_test_impl) {}

public:
    void non_virtual_test() { cout << 6 << endl; }
};

第二部分

现在很清楚,虚拟函数是使用 vtable 实现的,vtable 只是一堆函数指针,所以应该很清楚这段代码的作用:

#include <iostream>

using namespace std;

class my_base
{
    public:
            void non_virtual_test() { cout << 4 << endl; }
    virtual void virtual_test()     { cout << 5 << endl; }
};

class my_derived : public my_base
{
public:
    void non_virtual_test() { cout << 6 << endl; }
    void virtual_test()     { cout << 7 << endl; }
}

int main()
{
    my_base* base_obj = new my_derived();

    // This outputs 4, since my_base::non_virtual_test() gets called,
    // not my_derived::non_virtual_test().
    base_obj->non_virtual_test();

    // This outputs 7, since the vtable pointer points to
    // my_derived::virtual_test(), not to my_base::virtual_test().
    base_obj->virtual_test();

    // We shall not forget
    // there was an object that was pointed by base_obj
    // who happily lived in the heap
    // until we killed it.
    delete base_obj;

    return 0;
}

第三部分

由于没有动物示例,任何虚函数示例都是不完整的......

#include <iostream>

using namespace std;

class animal
{
public:
    virtual void say_something()
    { cout << "I don't know what to say." << endl
           << "Let's assume I can growl." << endl; }

    /* A more sophisticated version would use pure virtual functions:
     *
     * virtual void say_something() = 0;
     */
};

class dog : public animal
{
public:
    void say_something() { cout << "Barf, barf..." << endl; }
};

class cat : public animal
{
public:
    void say_something() { cout << "Meow, meow..." << endl; }
};

int main()
{
    animal *a1 = new dog();
    animal *a2 = new cat();
    a1->say_something();
    a2->say_something();
}

ABSTRACT

In this paper, we discuss virtual functions in C++. Part zero explains how virtual functions are declared and overridden. Part one attempts (and perhaps fails) to explain how virtual functions are implemented. Part two is a sample program that uses the example classes defined in parts zero and one. Part three is the classic animal example given in every virtual function - polymorphism tutorial.

PART ZERO

A method of a class is said to be virtual if and only if its declared to be so.

class my_base
{
public:
            void non_virtual_test() { cout << 4 << endl; } // non-virtual
    virtual void virtual_test()     { cout << 5 << endl; } // virtual
};

(Of course, I am assuming the programmer did not previously do anything like #define virtual.)

A class that redeclares and re-implements a non-virtual method of one of its bases is said to overload that method. A class that redeclares and re-implements a virtual method of one of its bases is said to override that method.

class my_derived : public my_base
{
public:
    void non_virtual_test() { cout << 6 << endl; } // overloaded
    void virtual_test()     { cout << 7 << endl; } // overriden
};

PART ONE

When the compiler detects a class has virtual methods, it automatically adds a virtual method table (also known as vtable) to the class' memory layout. The result is similar to what would have been generated from compiling this code:

class my_base
{
//<vtable>
// The vtable is actually a bunch of member function pointers
protected:
    void (my_base::*virtual_test_ptr)();
//</vtable>

// The actual implementation of the virtual function
// is hidden from the rest of the program.
private:
    void virtual_test_impl() { cout << 5 << endl; }

// Initializing the real_virtual_test pointer in the vtable.
public:
    my_base() : virtual_test_ptr(&my_base::virtual_test_impl) {}

public:
    void non_virtual_test() { cout << 4 << endl; }
    // The interface of the virtual function is a wrapper
    // around the member function pointer.
    inline void virtual_test() { *virtual_test_ptr(); }
};

When the compiler detects a class has overridden a virtual method, it replaces its associated entry in the vtable. The result is similar to what would have been generated from compiling this code:

class my_derived : public my_base
{
// The actual implementation of the virtual function
// is hidden from the rest of the program.
private:
    void virtual_test_impl() { cout << 7 << endl; }

// Initializing the real_virtual_test pointer in the vtable.
public:
    my_derived() : virtual_test_ptr(&my_derived::virtual_test_impl) {}

public:
    void non_virtual_test() { cout << 6 << endl; }
};

PART TWO

Now that it's clear that virtual functions are implemented using vtables, which are nothing but a bunch of function pointers, it should be clear what this code does:

#include <iostream>

using namespace std;

class my_base
{
    public:
            void non_virtual_test() { cout << 4 << endl; }
    virtual void virtual_test()     { cout << 5 << endl; }
};

class my_derived : public my_base
{
public:
    void non_virtual_test() { cout << 6 << endl; }
    void virtual_test()     { cout << 7 << endl; }
}

int main()
{
    my_base* base_obj = new my_derived();

    // This outputs 4, since my_base::non_virtual_test() gets called,
    // not my_derived::non_virtual_test().
    base_obj->non_virtual_test();

    // This outputs 7, since the vtable pointer points to
    // my_derived::virtual_test(), not to my_base::virtual_test().
    base_obj->virtual_test();

    // We shall not forget
    // there was an object that was pointed by base_obj
    // who happily lived in the heap
    // until we killed it.
    delete base_obj;

    return 0;
}

PART THREE

Since no virtual function example is complete without an example with animals...

#include <iostream>

using namespace std;

class animal
{
public:
    virtual void say_something()
    { cout << "I don't know what to say." << endl
           << "Let's assume I can growl." << endl; }

    /* A more sophisticated version would use pure virtual functions:
     *
     * virtual void say_something() = 0;
     */
};

class dog : public animal
{
public:
    void say_something() { cout << "Barf, barf..." << endl; }
};

class cat : public animal
{
public:
    void say_something() { cout << "Meow, meow..." << endl; }
};

int main()
{
    animal *a1 = new dog();
    animal *a2 = new cat();
    a1->say_something();
    a2->say_something();
}
数理化全能战士 2024-08-27 19:08:18

当来自 Java 时,人们可能会发现虚拟成员函数与非虚拟成员函数的概念令人困惑。需要记住的是,Java 方法对应于 C++ 中的虚拟成员函数。

问题不在于为什么我们实际上有虚函数,而在于为什么我们有非虚函数?我向自己证明它们的合理性(如果我错了,请纠正我)是它们的实现成本更低,因为对它们的调用可以在编译时解决。

When coming from Java, one might find the concept of virtual vs. non virtual member functions confusing. The thing to remember is that Java methods correspond to virtual member functions in C++.

The question is not so much why we actually have virtual functions, but why do we have non-virtual ones? The way I justify them to myself (correct me if I'm wrong) is that they are cheaper to implement, as calls to them can be resolved at compile time.

听风吹 2024-08-27 19:08:18

虚函数的存在是为了帮助设计基类的行为。纯虚函数的基类不能被实例化,称为抽象类。

由派生类来实现基类中的虚函数所描述的那些方法。然后可以实例化派生类(它们存在并占用内存)。

从派生类派生可以重新定义父对象中已定义的函数。这种技术您已经知道为覆盖,并允许您自定义该子对象的行为。

随着您对 C++ 的了解越来越多,您会发现继承并不像人们所吹捧的那样。组合通常是更好的选择。玩得开心。

Virtual functions exist to help design the behavior of a base class. A base class of pure virtual functions cannot be instantiated and is called an abstract class.

It's up to the derived classes to implement those methods described by the virtual functions in the base class. Derived classes can then be instantiated (they exist and occupy memory).

Deriving from derived classes can redfine a function already defined in the parent object. This technique you already know as overriding and allows you to customize the behavior of this child object.

As you learn more C++, you'll find that inheritance isn't all that it's cracked up to be. Composition and is often a better alternative. Have fun.

獨角戲 2024-08-27 19:08:18

典型的例子是一个绘画程序,其中使用虚拟的draw()函数创建基本Shape类。然后,每个形状(圆形、矩形、三角形等)都可以创建为子类,每个形状都以适当的方式实现其绘制()函数,并且核心绘制程序可以保留一个形状列表,每个形状都将执行适当的绘制( ) 函数,即使只存储了指向 Shape 基类的指针。

The classic example is that of a paint program where a base Shape class is created with a virtual draw() function. Then each of the shapes (circle, rectangle, triangle, etc) can be created as subclass that each implement their draw() function in the appropriate manner and the core paint program can keep a list of Shapes that will each do the appropriate draw() function even though only a pointer to the base Shape class is stored.

滥情哥ㄟ 2024-08-27 19:08:18

区别仅在于当您通过指向基类对象的指针调用派生类的方法时。在那一刻,如果您调用的方法在派生类中被重写,您将获得基类的执行,而如果是虚拟的,则您将获得派生类方法的执行。

#include <iostream>

class A{
    public:
    virtual void getA() { std::cout << "A in base" << std::endl;};
};

class B : public A {
    public:
    void getA() { std::cout << "A in derived class" << std::endl;}
};

int main(int argc, char** argv)
{
    A a;
    B b;
    a.getA();
    b.getA();

    A* t = new B;
    t->getA();
}

例如:在这个程序中 t->getA() 打印 "A in dependent class",但是如果基类 A 中没有 virtual 修饰符,那么它会打印“A in base”

希望有帮助。

The difference is just used when you call the method of the derived class, through a pointer to a base class object. In that moment you if the method you're calling was override in the derived class, you'll get the exceution of the base class, instead if was virtual then you got the execution of the derived class method.

#include <iostream>

class A{
    public:
    virtual void getA() { std::cout << "A in base" << std::endl;};
};

class B : public A {
    public:
    void getA() { std::cout << "A in derived class" << std::endl;}
};

int main(int argc, char** argv)
{
    A a;
    B b;
    a.getA();
    b.getA();

    A* t = new B;
    t->getA();
}

For example: in this program t->getA() print "A in derived class", but if there'were no virtual modificator in the base class A, then it would print "A in base".

Hope it helps.

无法言说的痛 2024-08-27 19:08:18

直升机和飞机都会飞行,但它们的飞行方式不同——它们都是某些假设对象 Flyer 的实例。您可以要求 Flyer 对象“飞行”——但 Flyer 只是一个接口,除了它应该能够飞行之外,它不知道有关飞行的任何信息。

然而,如果直升机和飞机都遵循传单的界面,那么如果有一个机场对象并且您给了它一个传单,那么机场需要做的就是请求传单飞行。

例如:

Airplace X=Airplane X("boeing 747");
Airfield::takeoff(&X);

Helicopter Y= Helicopter("Comache");
Airfield::takeof(&Y);

void Airfield::takeOff(Flyer * f)
{
     f->fly();
}

C++ 是一种严格的类型安全语言,只有在为对象层次结构启用 RTTI 且限定成员函数 virtual 时才可能实现这种功能(通过基类间接调用派生类的函数)。 。

Helicopters and airplanes both fly, but they do it in different ways -- they are both instances of some hypothetical object Flyer . You can ask the Flyer object to "fly" -- but Flyer is just a interface It doesn't know anything about flying other than that it should be able to fly.

However if both the helicopter and airplane follow the interface of flyer, than if had an airfield object and you gave it a Flyer all the airfield needs to do is to request the flyers to fly.

For example:

Airplace X=Airplane X("boeing 747");
Airfield::takeoff(&X);

Helicopter Y= Helicopter("Comache");
Airfield::takeof(&Y);

void Airfield::takeOff(Flyer * f)
{
     f->fly();
}

C++ is a strict type-safe language, and this sort of functionality (making function calls to derived classes indirectly via a base class) is only possible when RTTI is enabled for the object hierarchy, and qualifying a member function virtual enables this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文