Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C+;中,描述虚函数的最简洁而又准确的方法是什么+;? 被问及描述虚拟函数是什么,似乎是评估基本C++知识的面试中最常见的问题之一。然而,经过几年C++编程,我仍然有一种不舒服的感觉,我真的不知道如何最好地定义它们。_C++_Oop_Function_Polymorphism_Virtual - Fatal编程技术网

在C+;中,描述虚函数的最简洁而又准确的方法是什么+;? 被问及描述虚拟函数是什么,似乎是评估基本C++知识的面试中最常见的问题之一。然而,经过几年C++编程,我仍然有一种不舒服的感觉,我真的不知道如何最好地定义它们。

在C+;中,描述虚函数的最简洁而又准确的方法是什么+;? 被问及描述虚拟函数是什么,似乎是评估基本C++知识的面试中最常见的问题之一。然而,经过几年C++编程,我仍然有一种不舒服的感觉,我真的不知道如何最好地定义它们。,c++,oop,function,polymorphism,virtual,C++,Oop,Function,Polymorphism,Virtual,如果我查阅维基百科,我看到虚拟函数的定义是: 在面向对象编程中,虚函数或虚方法是一个函数或方法,其行为可以在继承类中被具有相同签名的函数重写 这个定义似乎简单而优雅,而不是C++特定的。但对我来说,它似乎并没有捕获C++中的虚函数的概念,因为一个非虚函数也可以通过一个具有相同签名的函数在继承类中重写。 如果我被要求非正式地描述虚拟函数是什么,我会说一些关于指针的东西,比如“它是一个方法,当你通过基类指针调用它时,如果指针实际指向派生类的实例,那么就会调用派生类中定义的虚函数的版本”。这似乎不是一

如果我查阅维基百科,我看到虚拟函数的定义是:

在面向对象编程中,虚函数或虚方法是一个函数或方法,其行为可以在继承类中被具有相同签名的函数重写

<>这个定义似乎简单而优雅,而不是C++特定的。但对我来说,它似乎并没有捕获C++中的虚函数的概念,因为一个非虚函数也可以通过一个具有相同签名的函数在继承类中重写。 如果我被要求非正式地描述虚拟函数是什么,我会说一些关于指针的东西,比如“它是一个方法,当你通过基类指针调用它时,如果指针实际指向派生类的实例,那么就会调用派生类中定义的虚函数的版本”。这似乎不是一个非常优雅的概念描述。我知道人们说这就是C++中的“多态”是如何实现的(多态性,据我所知,大致上是将对象组织成层次结构的整体思想),但我不知道用这种方法来理解或解释机制比用指针来处理这个例子更为令人费解。 <>我想我对虚拟函数的“指针”描述是否是他们定义的基础,或者只是在C++中实现它们的偶然性感到困惑。p> 当然,非虚函数也可以在继承类中被具有相同签名的函数重写


不,那是不对的。在这种情况下,函数只会被重新定义而不会被重写。

您的非正式定义是对虚拟指针功能的一个很好的总结。听起来你也在寻找它是如何工作的,但是因为C++标准没有指定,任何“如何”描述都是针对特定的实现而不是C++语言的。 <> P> C++标准是关于行为的,几乎不涉及实现。甚至还有“以貌取人”的规则,它允许提供相同的可见行为的任何可替代的实现。

“强”。我想我对虚拟函数的“指针”描述是否是它们的定义的基本概念感到困惑,或者只是在C++中实现它们的附带的东西。< /强>

这不是偶然的。虚函数的概念仅适用于指针或引用


当具有与基类相同签名的派生类方法被重写为不同的功能时,需要虚拟函数

class Polygon
{
    public:
    virtual float area()
    {
        std::cout << "\n No formula in general \n" ;
    }
    virtual ~Polygon();
};

class Square
{
    public:
    float area()
    {
        std::cout << "\n Side*Side \n" ; 
    }
    ~Square();
}

Polygon* obj = new Square ;
obj -> area() ;  // Ok, Square::area() is called. 

Square obj1;
Polygon& temp = obj1 ; // Ok, Square::area() is called

Square obj2;
Polygon temp1 = obj2 ; // Polygon::area() is called because of object slicing.
类多边形
{
公众:
虚拟浮动区()
{

std::cout我一直认为这句话抓住了虚拟函数的本质:

虚拟功能是定义一系列相关行为的一种方式,这些行为可以由实际执行这些行为的实体自定义

如果忽略虚拟函数的所有C++-ISM—使用虚拟函数如何使
dynamic_cast
对类类型的对象起作用,如何仅在通过指针访问时才对它们进行虚拟处理,虚拟析构函数与虚拟非析构函数如何完全不同,等等—我认为上述语句可以理解虚拟功能的核心是什么

我喜欢这句话的主要原因是,它以一种将虚拟函数与编程分离的方式来描述虚拟函数。你可以通过给出一些具体的类比,用这个定义向非技术人员解释虚拟函数。例如,“开灯”的想法可以被认为是一个虚拟的功能,因为当你打开一盏灯时发生什么的实际机制完全取决于你使用的特定灯光(白炽灯?荧光灯?LED?),但概念上的想法在每种情况下都是相同的。当然,这不是一个完美的类比,但我认为它足够清楚地表达了这一点


更一般地说,IMHO,如果你被要求以非正式的方式描述某件事,尽量远离你正在使用的特定编程语言,如果可能的话,尽量远离计算机。试着想想这个概念应用的最普遍的环境,然后在这个层次上描述它。然后,我再次教授CS入门课程,因此我对这个领域有一点偏见,所以我不知道这在面试环境中有多适用。:-

区别在于编译器如何决定“绑定”哪个实现编译源代码时调用方法。对于虚拟函数,选择的实现基于对象本身的实际具体类型,而不是变量的类型。这意味着当您将对象强制转换为基类或接口时,将执行的实现仍然是实现在派生类上定义的对象的实际位置

在puesdo代码中

// for a virtual function
public class Animal { public virtual void Move() { Print "An animal Moved." } }
public class Dog: Animal  { public void Move() { Print "A Dog Moved." } }

Animal x = new Dog();
x.Move()  // this will print "A Dog Moved."
对于非虚函数,选择的实现将基于变量的类型,这意味着当您将对象强制转换为基类时,(即,更改变量的类型)基类中定义的方法实现将由编译器选择并执行,而不是派生类中的实现

// for a non-virtual function
public class Animal { public void Move() { Print "An animal Moved." } }
public class Dog: Animal  { public void Move() { Print "A Dog Moved." } }

Animal x = new Dog();
x.Move() // this will print "An animal Moved."

假设Beta是Alpha的一个子类,它可以创建一个新的方法area(),也可以添加一个虚拟方法area

如果你是在和测试版的指针说话,没有什么区别。但是如果你是在说话