C ++ - 可以用不同的方式执行函数吗?

时间:2011-06-09 15:22:01

标签: c++

在此代码中:

void Window::oops()  { printf("Window oops\n"); } 
void TextWindow::oops() { 
printf("TextWindow oops %d\n", cursorLocation);
}
TextWindow x; 
Window      a; 
Window     *b; 
TextWindow *c; 
a = x; a.oops();   // executes Window version 
b = &x; b->oops(); // executes TextWindow or Window version 
c = &x; c->oops(); // executes TextWindow version

b = &x; b->oops();执行TextWindow 窗口版本意味着什么?怎么决定?

4 个答案:

答案 0 :(得分:4)

如果oops()是虚拟的,则b->oops()来电将使用TextWindow版本。如果不是,则使用Window版本。

答案 1 :(得分:1)

虽然没有具体说明,但我假设TextWindow来自Window(直接或间接)。

在这种情况下,基本问题是oops()是否是虚拟成员函数。

如果oops()是虚拟的,则通过指针或引用进行的调用基于 dynamic 类型 - 指针/引用实际引用的对象的类型。 / p>

如果oops()不是虚拟的,则通过指针或引用进行的调用基于 static 类型 - 指针定义为指向的对象类型,无论它实际指向的对象类型。

struct Window { 
    void oops() { std::cout << "Window::oops()\n"; }
    virtual void oops2() { std::cout << "Window::oops2()\n"; }
};

struct TextWindow : Window { 
    void oops() { std::cout << "TextWindow::oops()\n"; }
    virtual void oops2() { std::cout << "TextWindow::oops2()\n"; }
};

int main() { 
    Window w;
    w.oops();      // Both of these print "Window::...".
    w.oops2();

    TextWindow tw;
    tw.oops();     // Both of these print "TextWindow::...".
    tw.oops2(); 

    Window &w2 = tw;
    w2.oops();     // oops() is not virtual, and we're using a reference to a Window, 
                   // so this invokes Window::oops().

    w2.oops2();    // oops2() is virtual, so even though w2 is a reference to a
                   // Window, this invokes TextWindow::oops2(), because the reference
                   // refers to the object tw, which is a TextWindow.

    return 0;
}

答案 2 :(得分:0)

a = x; a.oops();   // executes Window version 

这个导致对象切片。请参阅此wiki条目:Object slicing

b = &x; b->oops(); // executes TextWindow or Window version 

使用它,您可以多态调用虚函数。它将调用TexTWindow文章,而不是Window版本!

c = &x; c->oops(); // executes TextWindow version

它只使用相同类型的指针调用虚函数作为对象的动态类型,在本例中为TextWindow

答案 3 :(得分:0)

这是基本的polymorphism

b是指向Window的指针,它可以指向Window对象或从Window继承的类型的对象。然后,继承的类型可以重新实现oops()函数(如果在Window定义中将oops()指定为虚拟)。

为了实现这一点,c ++编译器将添加额外的信息以在对象数据中路由函数调用,几乎总是以v-table的形式。

允许你操作一组Windows,调用基本成员函数,不要担心对象最终会做什么。然后,该对象可以以特定的方式为其特定的子类型实现函数。

请参阅维基百科页面中的简单示例:http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming