查询C++中的运行时多态性
query on runtime polymorphism in C++
class base
{
public:
virtual void showbase() {
// ----------
}
};
class base1 {
public:
virtual void showbase1() {
// -------
}
};
class derived : public base, public base1
{
void showbase() {
// ----
}
void showbase1() {
// -------
}
};
int main()
{
base* p = new derived();
p->showbase1();
base1* p1 = new derived();
p1->showbase();
}
根据我对虚拟函数的理解,编译器使用运行时(vtable机制)处理它,那么为什么我得到编译时错误。
若要模拟编译器,请考虑编译器看到的内容:
class base
{
public:
virtual void showbase() {
// ----------
}
};
base* p = /*blah blah*/;
p->showbase1();
是的,base
是一个多态类。 p
确实是一个指向base
的指针。 但是由于p
只指向一个base
,重要的是不指向一个base1
(showbase1
居住的地方),编译器像这样解释上面的代码。 显然,我在解释:
Here is a class named `base` with a single virtual method called `showbase`. Here is a pointer to a `base` object. Call the method named `showbase1`
编译器抱怨:
嗯,对不起,伙计,但
base
没有一种叫做的方法showbase1
.
你问:
[我]对虚函数的理解是编译器处理 它在运行时。 为什么我收到编译时错误?
因为你写的代码是无稽之谈。 这里基本上是多态性的工作原理。
- 使用虚拟方法定义基类。
- 定义重写这些虚拟方法的派生类。
- 编译器创建一个 vtable,该表将基类中方法的名称映射到派生类中的实现。
- 通过指向基类的指针(或 ref)调用基类中的方法时,将调用派生类的实现。
但您要做的是:
- 使用虚拟方法定义基类。
- 定义重写这些虚拟方法的派生类。
- 在完全不同的类中调用函数。
根据我对虚拟函数的理解,编译器使用运行时(vtable机制)处理它,那么为什么我得到编译时错误。
"处理它"是相当模糊的,vtables不是魔法;在C++虚拟调度允许调用的实际函数覆盖静态声明的虚拟函数。这意味着在编译时必须知道被覆盖的函数。
vtable 不包含在运行时查找函数所需的信息。相反,它基本上只是一个指向覆盖函数的指针列表。该基提供了其虚拟函数的完整列表,因此,给定特定的基类型,编译器在编译时知道该基的 vtable 中的位置以进行特定函数覆盖;编译器可以生成直接转到 vtable 中该位置的代码,获取指针并调用重写函数。
然后,在运行时,当创建派生类型的实际对象时,派生对象的构造函数填充基的 vtable,以便检查 vtable 的任何内容都将获得指向派生类型函数的指针。
所以你的代码的问题在于你正在调用的函数showbase()
不在编译器知道你正在访问的类型的虚函数列表中,base1
;编译器无法知道base1's
vtable 中的哪个位置获取名为 showbase()
的函数覆盖的指针,因为在 base1
的 vtable 中没有这样的条目。
指向派生类的基类指针只能访问基类中定义的成员函数。尝试通过它访问派生类中定义的其他函数是非法的。在您的情况下base
类没有定义showbase1
因此这是非法
base* p = new derived();
p->showbase1(); //illegal
但是,您可以这样做:
p->showbase(); // legal because showbase is a member function of base
同样,无法使用base
类指针访问showbase1
base1* p1 = new derived();
p1->showbase(); //illegal
p1->showbase1(); //legal
基类只知道它们自己的成员函数,所以你不能这样使用它。 您可以改为这样做:
base* p = new derived();
p->showbase();
base1* p1 = new derived();
p1->showbase1();
为了回答您关于运行时多态性的问题,正如您所说,它正在通过 vtable 处理运行时多态性(后期绑定)。 但是对于多重继承,每个基类基本上都有一个 vtable。 不能通过指向另一个基类的指针访问一个基类的 vtable。
p'static 类型 s 类型是 base,因此你只能用它调用已定义到 base 中的函数,即使在最后,它也会被调用 Derived 的函数,因为 P 的动态类型是派生的
同样的事情发生在 p1 上。
也许你的意思是p->showbase();
和p1->showbase1();
- 为什么我们实际上需要运行时多态性?
- 运行时多态性和dynamic_cast需要澄清
- 运行时多态性 - 箭头运算符访问了错误的成员?
- C ++中的方法覆盖:是编译时还是运行时多态性?
- 运行时与编译时多态性:更好的可读性与编译时错误检查,更重要的是
- 两个不同类的运行时多态性
- 考虑 .(点)应用于应该是运行时多态性的东西时
- 使用数组对对象的编译时多态性是否可行?
- 编译时多态性运行时多态性是这样的吗
- CRTP的运行时多态性设计和策略
- 查询C++中的运行时多态性
- 需要使用模板解决运行时多态性的帮助
- 为什么不能在编译时解决运行时多态性?
- c++与java中运行时多态性的成本比较
- 为什么为模板实例化声明运行时多态性会导致链接器错误
- 编译时与运行时多态性在c++中的优缺点
- 允许运行时和编译时多态性的灵活方式
- c++中通过虚函数实现的运行时多态性
- 虚拟函数是在C++中实现运行时多态性的唯一途径吗
- c++中运行时和编译时多态性的区别