【问题标题】:c++ polymorphism, name resolution for derived classc ++多态性,派生类的名称解析
【发布时间】:2014-11-08 03:29:32
【问题描述】:
class Base {
public:
virtual void f(float) { cout << "Base::f(float)\n"; }
};
class Derived : public Base {
public:
virtual void f(int) { cout << "Derived::f(int)\n"; }
};
int main() {
Derived *d = new Derived();
Base *b = d;
b->f(3.14F);
d->f(3.14F);
}

-C++ 不支持逆变返回类型,所以 f(int) 不会覆盖 f(float)

-C++ 支持多态,因此 d 和 b 都应该指向派生类的 vtable。

-vtable 派生类类似于 0: f(float), 1: f(int) etc.

我对这个问题的回答是 Base::f(float) 被调用了两次,但答案是:

Base::f(float) Derived::f(int)

为什么会这样?从不同的指针访问派生类是否强制执行某些规则?据我所知,对象切片仅在使用 copy-ctor 或 copy-assignment 时发生,带有指针,它们都应该指向同一个 vtable。

【问题讨论】:

    标签: c++ polymorphism object-slicing


    【解决方案1】:

    不同类中的方法不会一起重载;在Derived 中定义另一个f() 可以防止在重载解决期间考虑Base 中的那个。

    当您想要添加新的重载而不隐藏基类中定义的重载时,您需要显式地将基定义引入派生类。

    public:
        using Base::f;
    

    【讨论】:

    • 为什么base-&gt;f指的是基函数?
    • 我也很好奇指针如何影响名称解析。
    • @0x499602D2 因为是通过指向Base的指针来访问的,所以编译器在执行重载解析时并不知道它实际上是一个Derived实例。重载解决发生在编译时,而不是在运行时。
    【解决方案2】:

    我对此的看法是,当您调用 d-&gt;f(3.14F) 时,float 会隐式转换为 int

    您的Derivedclass 实际上有 2 个 f() 条目

    void f(int);
    void f(float);
    

    这由带有 -fdump-class-hierarchy 标志的 g++ 确认。我们可以看到输出如下:

    Vtable for Base
    Base::_ZTV4Base: 3u entries
    0     (int (*)(...))0
    4     (int (*)(...))(& _ZTI4Base)
    8     (int (*)(...))Base::f
    
    Vtable for Derived
    Derived::_ZTV7Derived: 4u entries
    0     (int (*)(...))0
    4     (int (*)(...))(& _ZTI7Derived)
    8     (int (*)(...))Base::f
    12    (int (*)(...))Derived::f
    

    您的Derived 类没有触及基类中的 f 函数,因为定义不匹配。代码可以编译,因为在 float 和 int 之间存在隐式转换。

    试试下面的

    class Derived : public Base {
    public:
    virtual void f(std::string) { cout << "Derived::f(string)\n"; }
    };
    

    那么这段代码将不会编译,因为 Derived:f(...) 将隐藏 Base::f(...) 定义。这通常被称为继承阴影。

    因此调用 b->f(3.14F) 将在 Base 表中解析,而 d->f(3.14F) 将在 Derived 表中解析,这会影响 Base。

    【讨论】:

    • 回首往事,我刚刚意识到没有发生覆盖应该很明显,因为 C++ 不支持逆变参数!
    猜你喜欢
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 2013-06-24
    相关资源
    最近更新 更多