I'm testing this code and wondering why this wasn't failed at compile time ?. I'm using c++11 and g++ 4.7.2.
I had similar structure on my production code, it was giving errors at run time, then I found that I'm constructing the class with wrong argument type.
#include <iostream>
#include <vector>
typedef std::vector<std::string> Word;
class Data {
public:
const Word &word;
Data(Word w) : word(w) {}
};
class Base{
const Data &data;
public:
Base(const Data &d): data(d) {}
~Base() {}
};
class Work : public Base{
public:
Work(const Data &d): Base(d){}
~Work() {}
};
int main(int argc, char **argv){
Word words;
words.push_back("work");
/*
* I'm confused with this constructor, why this passed the compilation
* ??
* Any special rule to reason this scenario ??
*
* But obviously it will fail at run time.
*/
const Work *work = new Work(words);
return 0;
}
Data
is constructible from Word
, so you can pass a Word
to the Work
constructor. Under the hood, an instance of Data
will be created from the passed Word
and, in turn, passed to the constructor.
You can avoid this by marking the constructor of Data
that takes a Word
as explicit, like this:
class Data {
public:
const Word &word;
explicit Data(Word w) : word(w) {}
};
That way, the constructor cannot be implicitly applied anymore, and your call to the Work
constructor will fail to compile unless you explicitly invoke the Data
constructor:
const Work *work = new Work(words); // Implicit call, fails to compile.
const Work *work = new Work(Data(words)); // Explicit call, compiles.
It works compiles* because Data
has an implicit conversion constructor that takes a Word
reference:
Data(Word w) : word(w) {}
This means you can do things such as
Word words;
Data d1 = words;
Data d2(words);
and you can construct a Work
from a Data
via constructor Work(const Data &d): Base(d){}
:
Work w(d2);
which means the following is also valid, because it only involves one user-defined conversion:
Work w2(words); // constructs Data temporary from words, then constructs w2 with it
This behaviour can be suppressed by declaring the converting constructor as explicit
:
explicit Data(Word w) : word(w) {}
* Your doesn't actually work because it involves a dangling reference to a temporary Data
object
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With