C ++多态函数匹配

时间:2016-05-25 23:29:59

标签: c++ polymorphism

我的代码下面是带有虚函数的链继承,它打印出来:

D ptr
E

那么函数匹配的算法是什么,我的猜测是它匹配最近的父类?但是& e基本上是A *,B *,D *类型,为什么这甚至编译并且使用这个属性是好的做法?

#include <iostream>

using namespace std;

class A {
    public:
        virtual void f(){cout<<"A";};
};

class B :public A {
    public:
    virtual void f() {
        cout<<"B";
    }
};

class D : public B {
    public:
    virtual void f() {
        cout<<"D";
    }
};

class E : public D {
    public:
    virtual void f() {
        cout<<"E";
    }
};

void f(D *sth) {
    cout<<"D ptr"<<endl;
    sth->f();
}

void f(B *sth) {
    cout<<"B ptr"<<endl;
    sth->f();
}

void f(A *sth) {
    cout<<"A ptr"<<endl;
    sth->f();
}

int main() {
    E e;
    f(&e);
}

2 个答案:

答案 0 :(得分:0)

我会尽力打破你的榜样:

int main() {
    E e;    // declare object of Class E
    f(&e);  // run f() function and pass it the address of E
}

好的很简单 - 您声明了一个E类对象,然后在其上运行了一个函数。现在全局f()函数已经重载三次以接受指向D对象,B对象或A对象的地址的指针。由于所有这些都将对象更高地放在继承树上,因此任何对象都适用于E类对象。编译器将为最派生类选择函数。在这种情况下,选择void f(D * sth)函数。

void f(D *sth) {
    cout<<"D ptr"<<endl; // "D ptr" printed to screen
    sth->f();            // Take original pointer to class E object and 
                         // run its own class method f() on it
}

然后查看E的类定义,我们将看到E打印的原因:

class E : public D {
    public:
    virtual void f() {
        cout<<"E";
    }
};

如果你要注释掉void f(D * sth)函数,编译器会改为选择void f(B * sth)函数,从而得到输出&#34; B ptr&#34;和&#34; E&#34;。如果您要注释掉A和B对象的全局f()函数,然后尝试在B对象上运行void f(D * sth),它将无法编译,因为编译器只能将对象转换为继承树,而不是它。

正如Phil1970评论的那样,这种结构通常不受欢迎,因为它依赖于具有继承树知识的全局函数。

答案 1 :(得分:0)

它应该给你一个未定义的行为或歧义。不同的编译器版本可以提供不同的结果,因此您最好不要依赖于您的结果:)