This is totally unexpected (for me atleast…) behaviour I encountered in C++. I
was using g++ version 3.4.2 (DevC++) 

class Base{
public:
       Base() { cout << "Base ctor..." << endl;  }
       virtual ~Base() { cout << "~Base called..." << endl; }

virtual void Show() const
       {
               cout << "Base show called..." << endl;
       }
};

class Derived: public Base{
public:
       Derived() { cout << "Derived ctor..." << endl; }
       ~Derived() { cout << "~Derived called..." << endl; }

virtual void Show() const
       {
               cout << "Derived show called..." << endl;
       }
};

Now I used the tertiary operator to create the objects of derived and base.
Following is the piece of code which does this…

   {
        bool bFlag = false;
        const Base& ref = (bFlag)? Base(): Derived();
        ref.Show();
    }

This code works as expected when the value of "bFlag" is true but the whole
problem come when the value of bFlag is false…
Output

Base ctor...
    Derived ctor...
    ~Derived called...
    ~Base called...
   Base show called...
   ~Base called...

So you might notice that the destructor of Derived class is being called before
the function Sow is called. And more over the Show function called is of Base
instead of Derived….i.e. Instead of Derived's object Base's object is created..

Extract from the C++ standard!!!

=> if the second and third operand have different types, and either has
(possibly cv-qualified) class type, an attempt is made to convert each of those
operands to the type of the other. The process for determining whether an
operand expression E1 of type T1 can be converted to match an operand
expression E2 of type T2 is defined as follows:

…..— if E1 and E2 have class type, and the underlying class types are the same
or one is a base class of the other: E1 can be converted to match E2 if the
class of T2 is the same type as, or a base class of, the class of T1, and the
cv-qualification of T2 is the same cv-qualification as, or a greater
cvqualification than, the cv-qualification of T1. If the conversion is applied,
E1 is changed to an rvalue of type T2 that still refers to the original source
class object (or the appropriate subobject thereof). [Note: that is, no copy is
made.]

…..

Using this process, it is determined whether the second operand can be
converted to match the third operand, and whether the third operand can be
converted to match the second operand. If both can be converted, or one can be
converted but the conversion is ambiguous, the program is ill-formed. If
neither can be converted, the operands are left unchanged and further checking
is performed as described below. If exactly one conversion is possible, that
conversion is applied to the chosen operand and the converted operand is used
in place of the original operand for the remainder of this section.
Opinion

Therefore, it is clear that a conversion is taking place but it is also made
clear that no copy is made "E1 is changed to an rvalue of type T2 that still
refers to the original source class object (or the appropriate subobject
thereof). [Note: that is, no copy is made.]"…. Therefore in the above example a
copy of "Base" is made instead of refering to "Derived" class object (can be
confirmed by checking the call to Show function). Which I think is a bug in
gcc.


-- 
           Summary: Tertiary operator: object creation and initialization
           Product: gcc
           Version: 3.4.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: joseph dot rajesh at gmail dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28169

Reply via email to