下面的代码带有带虚拟函数的链式继承,并打印:
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);
}发布于 2016-05-26 01:10:44
我将尽我最大的努力来打破你的榜样:
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 (D*某事物)函数。
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 (D*某事物)函数,则编译器将选择void (B*某事物)函数,从而输出"B ptr“和"E”。如果要注释掉A和B对象的全局f()函数,然后尝试在B对象上运行void (D*某某物),它将不会编译,因为编译器只能将对象转换到继承树上,而不能向下转换。
正如Phil1970所评论的那样,由于它依赖于具有继承树知识的全局函数,所以这种结构通常是不受欢迎的。
发布于 2016-05-26 01:16:49
它应该给你一个未定义的行为或模糊。不同的编译器版本可以提供不同的结果,所以最好不要依赖结果:)
https://stackoverflow.com/questions/37449246
复制相似问题