Re: Using "this" in a base initializer list?
On May 8, 8:16 pm, "Alf P. Steinbach" <a...@start.no> wrote:
* Victor Bazarov:
James Kanze wrote:
On May 8, 3:25 pm, "Victor Bazarov" <v.Abaza...@comAcast.net> wrote:
Angel Tsankov wrote:
Hello! Is the following code illformed or does it yield undefined
behaviour:
class a
{};
class b
{
public:
b(a&){}
};
class c: private a, private b
{
public:
c():b(*this){}
};
Neither. The code is fine.
Are you sure? Throw in some virtual inheritance, and it core
dumps with Sun CC. [..]
Huh? Throw in division by zero or dereferencing a null pointer
and it may release nasal demons. What's it got to do with the
code at hand?
James is referring to the conversion from c* to a*, which =A73.8/5 says is
Undefined Behavior. But the interpretation that yields that conclusion
also means that this,
struct S
{
void foo() {}
S() { this->foo(); }
};
is undefined behavior, so that the common technique of using an
init-function called from multiple constructors, would be formally
Undefined Behavior. Which really means that part of the standard is
fishy Fishy FISHY,
You get that feeling too. Realistically, at least some of the
uses must be defined, regardless of what the standard says. But
which ones?
and should not be taken verbatim: some constructive
interpretation required, and I think it's impossible to say whether the
code above is formally OK (or not), only that it's in-practice OK.
In this simple case. That's why I mentionned that I'd actually
had a problem with a real compiler in the past. It's because I
had the problem that I'd familiarized myself with the standard,
too. I wanted to complain about a compiler error, but the
standard didn't support me.
Logically, I still have trouble understanding *why* it should be
undefined behavior. The compiler must be able to do the
conversion, since it has to get the correct address for the this
pointer it passes to the base class constructors. In my case,
the code was very clear:
class MyStream
: public virtual MyStreambuf
, public std::ostream
{
} ;
The organization was such in order to ensure that the streambuf
was constructed before its address was passed to std::ostream.
Initializing std::ostream with this, however, resulted in the
wrong address being passed, and a core dump later, when ostream
used it. Removing the virtual worked. What also worked was
wrapping the streambuf:
template< typename Streambuf >
class StreambufWrapper
{
public:
std::streambuf* getStreambuf() { return &myStreambuf ; }
Streambuf myStreambuf ;
} ;
class MyStream
: public virtual StreambufWrapper< MyStreambuf >
: public std::ostream
{
public:
MyStream() : std::ostream( getStreambuf() ) {}
} ;
Obviously, the compiler had to do successfully convert this to a
pointer to the base class in order to call getStreambuf(), but
for who knows what reason, it was unable to do it correctly when
this was passed to the constructor.
--
James Kanze (Gabi Software) email: james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34