为什么在C ++中需要“对象切片”?为什么允许?有更多的错误? [英] Why is 'object slice' needed in C++ ? Why it is allowed ? For more bugs?

查看:124
本文介绍了为什么在C ++中需要“对象切片”?为什么允许?有更多的错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么C ++标准允许对象切片?

Why C++ standard allow object slice ?

请不要向我解释c ++对象切片的概念,因为我知道。

Please don't explain c++ object slice concept to me as I knew that.

这个c ++特性(对象切片)设计背后的意图是什么?

I am just wondering what's the intention behind this c++ feature(object slice) design ?

为新手提供更多错误?

下面是一个标准和基本的例子:

Below is just a standard and basic slice example:

class Base{
public:
       virtual void message()
       {
               MSG("Base ");
       }
private:
    int m_base;
};

class Derived : public Base{
public:
       void message()
       {
               MSG("Derived "); 
       }
private:
       int m_derive;
};

int main (void)
{
    Derived dObj;

    //dObj get the WELL KNOWN c++ slicing below
    //evilDerivedOjb is just a Base object that cannot access m_derive
    Base evilDerivedOjb = dObj;  //evilDerivedObj is type Base
    evilDerivedOjb.message();    //print "Baes" here of course just as c++ standard says
}

================================= ============================
阅读所有的答案和评论后,我想我应该更好地表达我的问题,但在这里它来:

================================================================================= After reading all the answers and comments I think I should express my question better in the first place but here it comes:

当有一个is-a关系公共继承),而不是私人/保护继承,你可以做以下:

When there is a is-a relationship(public inheritnace), instead of private/protected inheritance , you can do the following:

class Base{
public:
    virtual void foo(){MSG("Base::foo");}
};

class Derived : public Base{
public:
    virtual void foo(){MSG("Derived::foo");}
};

int main (void)
{
    Base b;
    Derived d;
    b = d;                      //1
    Base * pB = new Derived();  //2
    Base& rB = d;               //3

    b.foo();    //Base::foo
    pB->foo();  //Derived::foo
    rB.foo();   //Derived::foo
}

众所周知,

注意1,2和3 需要

如果您使用的是私有/保护继承,那么所有这些都将得到编译错误:

Note 1, 2 and 3 NEED is-a relationship to work.
If you are using private/protect inheritance, you will get compile error for all of them :

'type cast' : conversion from 'Derived *' to 'const Base &' exists, but is inaccessible
'type cast' : conversion from 'Derived *' to 'Base *' exists, but is inaccessible
'type cast' : conversion from 'Derived *' to 'Base &' exists, but is inaccessible

所以我的问题(原意)是要问如果c ++标准
更好一个编译错误,同时保持允许2和3吗?

So my question(original intention) was to ask would it be better if c++ standard make 1 a compile error while keep allowing 2 and 3 ?

希望我这次更好地表达我的问题。

Hope I have expressed my question better this time.

感谢

推荐答案

由于是-a 关系,所以允许。

>公开 1 基本派生派生编译器 Derived 是 c> 。因此,应该允许这样做:

When you publicly1 derive Derived from Base, you're annoucing to the compiler that Derived is a Base. Hence it should be allowed to do this:

Base base = derived;

,然后使用 base 即:

base.message(); //calls Base::message();

阅读:

  • Is-A Relationship

1。如果您私下地 Base 中派生派生,那么它是 has-a 关系。这是一种组成。阅读

1. If you privately derive Derived from Base, then it is has-a relationship. That is sort of composition. Read this and this.

但是,在你的情况下,如果你不想切片,那么你可以这样做:

However, in your case, if you don't want slicing, then you can do this:

Base & base = derived;
base.message(); //calls Derived::message();






从您的评论:


From your comment :


不能更好的C ++防止对象切片,而只允许指针/引用的工作is-a relationshp ???

Wouldn't it better for C++ to prevent object slicing while only allow the pointer/reference to work for is-a relationshp ???

否。如果基数具有虚函数,指针和引用不维持 is-a 关系。

No. Pointer and Reference doesn't maintain is-a relationship if the base has virtual function(s).

 Base *pBase = &derived;
 pBase->message(); //doesn't call Base::message(). 
 //that indicates, pBase is not a pointer to object of Base type.

当你想让一个类型的一个对象的行为像它的基类型的对象,调用 is-a 关系。如果你使用基本类型的指针或引用,那么它不会调用 Base :: message(),这表明,指针或引用不像指针,引用 类型的对象。

When you want one object of one type to behave like an object of it's base type, then that is called is-a relationship. If you use pointer or reference of base type, then it will not call the Base::message(), which indicates, pointer or reference doesn't have like a pointer or reference to an object of base type.

这篇关于为什么在C ++中需要“对象切片”?为什么允许?有更多的错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆