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