我想知道关于取消引用指向base的标准的标准视图,但我找不到任何进展。以这两个类为例:
class Base
{
public:
virtual void do_something() = 0;
};
class Derived : public Base
{
public:
virtual void do_something();
};
void foo2(Base *b)
{
Base &b1 = *b; // how this work by standard?
}
void foo()
{
Derived *d = new Derived();
foo2(d); // does this work by standard?
}
所以,基本上,如果对类型D的对象的类型B的指针被解除引用,那么切片是否会发生到位,或者临时会出现?我倾向于认为临时不是一种选择,因为这意味着临时是抽象类的实例。
无论事实如何,我都会感谢任何指向ISO标准的指示。 (或者第三,就此而言。:))
编辑:
我认为暂时不能作为一种选择,因为它可能的行为方式为什么它的行为方式,这是合乎逻辑的,但我找不到标准的确认,我不是一个普通的读者
EDIT2:
通过讨论,很明显我的问题实际上是解除引用指针机制,而不是关于拼接或临时。我感谢大家试图为我愚蠢,我终于得到了最让我困惑的问题的答案:为什么我在标准中找不到任何关于这个...显然这是错误的问题,但我得到了正确的答案。
日Thnx
答案 0 :(得分:4)
Base &b = *static_cast<Base *>(d); // does this work by standard?
是
但你可以这样做:
Base &b = *d;
//use b polymorphically!
b.do_something(); //calls Derived::do_something()
无需使用static_cast
。毕竟,Derived
来自Base
。
回复你的编辑:
foo2(d); // does this work by standard?
是。可以使用类型Base*
的指针初始化类型Derived*
的指针。
-
Base &b = *b; // how this work by standard?
没有。他们的名字相同。如果你的意思是,Base &b1 = *b
,那么是的,这是有效的。 b1
指的是b
指向的对象。
答案 1 :(得分:2)
在我的C ++ 11草案中,10 [class.derived] / 1表示
[注意:范围解析运算符::(5.1)可用于引用 明确的直接或间接基础成员。这允许访问 已在派生类中重新声明的名称。派生类 它本身可以作为受访问控制的基类;见11.2。 指向派生类的指针可以隐式转换为指针 到一个可访问的明确基类(4.10)。 a的左值 派生类类型可以绑定到对可访问的引用 明确的基类(8.5.3)。 - 后注]
在大多数实现中,您的foo2函数会将Base& b
存储为Base*
。它显然不能是Base
本身,因为那将是一个副本,而不是一个参考。由于它(在运行时,不是语法上)就像指针而不是副本一样,因此没有拼接问题。
在编辑之前的代码中,编译器会知道Base& b
实际上是d
,它会是语法糖,甚至不会在程序集中生成指针。
答案 2 :(得分:2)
只有当基类的复制构造函数或赋值运算符以某种方式涉及时,才会发生对象切片,就像参数传递值一样。例如,即使仅在DEBUG模式下,您也可以通过继承Boost的noncopyable
来轻松避免这些错误。
铸造指针或引用以及解除引用都不涉及任何复制构造或赋值。从Derived引用中创建Base引用是非常安全的,它甚至是标准的隐式转换。