与新操作符C++的静态绑定

与新操作符C++的静态绑定,c++,new-operator,static-binding,C++,New Operator,Static Binding,我想确定我是否正确理解这一点。如果我有类似的东西: Base* wsk = new Derived 若我用静态绑定实现了这一点,那个么wsk是基类型,但仍然创建了派生类型对象?wsk指向那个派生类型对象,但它不能使用派生类中的方法,因为wsk是基类型?总结一下,对我来说最重要的问题是,如果wsk除了它的基类型外,仍然指向新的派生类型的对象?wsk的类型是Base*,而不是Base或Derived 它是用一个从类型派生*隐式转换的值初始化的。它指向一个基本对象,它恰好位于派生对象中 这意味着st

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

Base* wsk = new Derived
若我用静态绑定实现了这一点,那个么wsk是基类型,但仍然创建了派生类型对象?wsk指向那个派生类型对象,但它不能使用派生类中的方法,因为wsk是基类型?总结一下,对我来说最重要的问题是,如果wsk除了它的基类型外,仍然指向新的派生类型的对象?

wsk的类型是Base*,而不是Base或Derived

它是用一个从类型派生*隐式转换的值初始化的。它指向一个基本对象,它恰好位于派生对象中

这意味着static_castwsk将为您提供一个指向派生对象的值

wsk的表示可能与static_castwsk的表示相同,即基本对象的地址与派生对象的地址相同,但不能保证wsk的类型为Base*,而不是Base或Derived

它是用一个从类型派生*隐式转换的值初始化的。它指向一个基本对象,它恰好位于派生对象中

这意味着static_castwsk将为您提供一个指向派生对象的值

wsk的表示可能与static_castwsk的表示相同,即基对象的地址与派生对象的地址相同,但这并不能保证

如上所述,当查看Base*时,它指向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!!
}
输出为:

从基地

从B

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

总而言之,这里有3个对象:

静态类型基和动态类型基的对象。 静态类型Base和动态类型A的对象。 静态类型Base和动态类型B的对象。 分别使用A或B函数的唯一方法是使用强制转换,以便将它们恢复为原始形式。但这应该谨慎行事

重要的评论:据我所知,这在任何提供多态性的语言中都是正确的。它不是唯一的C++! 如上所述,当查看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!!
}
输出为:

从基地

从B

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

总而言之,这里有3个对象:

静态类型基和动态类型基的对象。 静态类型Base和动态类型A的对象。 静态类型Base和动态类型B的对象。 分别使用A或B函数的唯一方法是使用强制转换,以便将它们恢复为原始形式。但这应该谨慎行事


重要的评论:据我所知,这在任何提供多态性的语言中都是正确的。它不是唯一的C++! 是的,它指向派生成员,但只能在强制转换为派生成员后使用派生成员。我觉得任何一本优秀的C++书籍或教程都会使这一点很清楚。当然,任何派生的虚拟方法都可以在没有铸造的情况下使用。@约翰,任何基于派生的虚拟方法。overrides@Caleth是的,感谢您的澄清。是的,它指向派生成员,但您只能在强制转换为派生成员后使用派生成员。我觉得任何一本优秀的C++书籍或教程都会使这一点很清楚。当然,任何派生的虚拟方法都可以在没有铸造的情况下使用。@约翰,任何基于派生的虚拟方法。overrides@Caleth是的,感谢您的澄清。它指向一个基本对象,它恰好位于派生对象中。-wsk在此指向派生类型的对象。@Swardfish否,它指向派生对象的基子对象没有子对象。如果你想在这个方向上争论,请带上参考资料。@swardfish每一个指令
t和间接基类作为基类子对象存在于派生类的对象表示中,位于实现定义的偏移量处@箭鱼或对象可以包含其他对象,称为子对象。子对象可以是成员子对象[class.mem]、基类子对象[class.derived]或数组元素。它指向一个基本对象,该对象恰好位于派生对象中。-wsk在此指向派生类型的对象。@Swardfish否,它指向派生对象的基子对象没有子对象。如果您希望在该方向进行辩论,请带上引用。@Swardfish每个直接和间接基类都作为基类子对象存在于派生类的对象表示中,位于实现定义的偏移量处@箭鱼或对象可以包含其他对象,称为子对象。子对象可以是成员子对象[class.mem]、基类子对象[class.derived]或数组元素。吹毛求疵:还有两个对象的类型是Base*,还有A*和B*类型的物质化临时对象@Caleth确实,为了解决问题的核心,我做了过度简化,补充了一条评论:@Kerek我仍然认为我的问题是正确的,但你的回答有助于澄清Caleth提到的内容。谢谢你。吹毛求疵:还有两个Base*类型的对象,还有A*和B*类型的物质化临时对象@Caleth确实,为了解决问题的核心,我做了过度简化,补充了一条评论:@Kerek我仍然认为我的问题是正确的,但你的回答有助于澄清Caleth提到的内容。谢谢你。