简体   繁体   中英

C++ ISO Standard interpretation of dereferencing pointer to base

I would like to know standard's view on dereferencing pointer to base, but I'm not making any progress finding it. Take these two classes for example:

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?
}

So, basically, if pointer of type B to an object of type D is dereferenced, will slicing happen in place, or temporary will emerge? I'm prone to believe that temporary is not an option, because that would mean that temporary is instance of abstract class.

Whatever the truth, I would appreciate any pointers to the ISO standard that says one or the other. (Or third, for that matter. :) )

EDIT:

I threw the point with temporary not being an option as a possible line of reasoning why it behaves the way it does, which is quite logical, but I can't find confirmation in standard, and I'm not a regular reader.

EDIT2:

Through discussion, it became obvious that my question was actually about dereferencing a pointer mechanism, and not about splicing or temporaries. I thank everyone for trying to dumb it down for me, and I finally got answer to the question the puzzled me the most: Why I can't find anything in the standard about this... Obviously it was the wrong question, but I've got the right answer.

Thnx

Base &b = *static_cast<Base *>(d); // does this work by standard?

Yes.

But you can simply do this:

Base &b = *d;

//use b polymorphically!
b.do_something(); //calls Derived::do_something()

No need to use static_cast . After all, Derived is derived from Base .


Reply to your edit:

foo2(d); // does this work by standard?

Yes. Pointer of type Base* can be initialized with pointer of type Derived* .

--

Base &b = *b; // how this work by standard?

No. They're same name. If you mean, Base &b1 = *b , then yes, that works. b1 refers to the object pointed to by b .

In my C++11 draft, 10 [class.derived] /1 says

[ Note: The scope resolution operator :: (5.1) can be used to refer to a direct or indirect base member explicitly. This allows access to a name that has been redeclared in the derived class. A derived class can itself serve as a base class subject to access control; see 11.2. A pointer to a derived class can be implicitly converted to a pointer to an accessible unambiguous base class (4.10). An lvalue of a derived class type can be bound to a reference to an accessible unambiguous base class (8.5.3). —end note ]

In most implementations, your foo2 function will store Base& b as a Base* . It obviously can't be a Base itself, because that would be a copy, not a reference. Since it acts (at runtime, not syntactically) like a pointer instead of a copy, there's no splicing concerns.

In your code before your edit, the compiler would know that Base& b was actually d , it would be syntactic sugar, and wouldn't even generate a pointer in the assembly.

Object slicing only occurs when the copy constructor or the assignment operator of the base class gets involved somehow, like in parameter passing by value. You can easily avoid these errors by inheriting from Boost's noncopyable for example, even if only in DEBUG mode.

Neither casting pointers or references nor dereferencing involve any copy construction or assignment. Making a Base reference from a Derived reference is perfectly safe, it's even a standard implicit conversion.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM