1

我想确定我是否理解正确。如果我有类似的东西:

Base* wsk = new Derived

如果我用静态绑定做到了这一点,那么 wsk 是 Base 类型,但仍然创建了派生类型对象?并且wsk指向该派生类型对象,但它不能使用派生类中的方法,因为wsk是基类型?总结对我来说最重要的问题是,如果wsk除了它的 Base 类型仍然指向 Derived 类型的新对象?

4

2 回答 2

3

如上所述,一个重要的评论Base *指向 type Base。我没有使用这个符号来简化解释。

您要问的是一个不同的问题:对象的静态类型动态/运行时类型之间有什么区别。

让我们观察以下代码:

#import <iostream>

class Base
{
    public:
    virtual void foo()
    {
        std::cout << "From Base" << std::endl;
    }
};

class A : public Base
{
    public:
    void foo() override
    {
        std::cout << "From A" << std::endl;
    }

    void some_A_only_function()
    {
        std::cout << "some function from A" << std::endl;
    }
};

class B : public Base
{
    public:
    void foo() override
    {
        std::cout << "From B" << std::endl;
    }

    void some_B_only_function()
    {
        std::cout << "some function from B" << std::endl;
    }
};


int main()
{
    Base base{};
    Base * a = new A();
    Base * b = new B();

    base.foo();

    a->foo();
    // a->some_A_only_function(); this won't compile: error: no member named 'some_A_only_function' in 'Base'

    b->foo();
    // b->some_B_only_function(); this won't compile either!!
}

输出是:

从基地

从一个

从乙

这里的所有对象都来自 的静态类型Base,因此,您不能调用任何不属于 的函数Base,因为编译器无法知道在运行时将哪种类型放入其中。如果我们有重写的函数,将根据运行时类型调用适当的函数(这称为动态调度)。

总结一下,这里有3个对象:

  1. 静态类型Base和动态类型的对象Base
  2. 静态类型Base和动态类型的对象A
  3. 静态类型Base和动态类型的对象B

A分别使用or函数的唯一方法B是使用强制转换将它们“返回”到它们的原始形式。但应该谨慎行事!

大评论:这实际上在任何提供多态性的语言中都是正确的(据我所知)。它不是 C++ 独有的!

于 2020-07-30T09:54:16.587 回答
2

wsk是类型Base *,不是Base也不是Derived

它使用从 type (隐式)转换的值初始化Derived *。它指向一个Base对象,而该对象恰好位于一个Derived对象中。

这意味着这static_cast<Derived *>(wsk)将为您提供一个指向 a 的值Derived

可能 的表示与的表示wsk相同,即对象的地址与对象的地址相同,但不能保证static_cast<Derived *>(wsk)BaseDerived

于 2020-07-30T09:38:51.187 回答