2

I have this simple code:

class A {
public:
    int m;
};

class B : public A {
public:
    B(const B& b) { /*...*/ }
    B(const A& a) { /*...*/ }
    int n;
};

const A& function()
{
    static A a;
    return a;
}

int main()
{
    const B& a = function();
    const int x = a.n; // !!!!! Error: probably reads some random mess

    /* ... */

    B b2 = function(); 

    /* ... */

    return 0;
}

In this code I demonstrate what can happen when you mistakenly write const B& a = function() instead of const A& a = function(). And the compiler does not catch this error! To catch this error at compile time, constructor B(const A& a) must be explicit. But marking constructor explicit disables ability to do B b2 = function(); — it must be written uglier: B b2(function());

Question: Does there exist some way to catch this type of error at compile time while keeping the possibility to write this?

B b2 = function();

EDIT: As is stated by @ditskowitch and @n.m. - what i am supposing to be error is not error. For that, explicit contructor is not needed. It can teoreticaly be problem only if depending code expects that reference returned by function() points at some address as showed by @Rory Yorke

user3123061
  • 757
  • 5
  • 14

2 Answers2

2

The compiler behaves properly: since your B class has a constructor, accepting const A& - you actually commit that B can be properly instantiated from the instance of A. So there should not be any "random mess" in x, but the value, which the constructor assigns for n, when constructing from instance of A

Denis Itskovich
  • 4,383
  • 3
  • 32
  • 53
  • But this is also bad. So, you say, compiler constructs temporary B. And then reference to this temporary is acessed later, but at this time that temporary B no longer exists! – user3123061 Feb 16 '14 at 07:57
  • 1
    @user3123061: this is not true. Lifetime of a temporary is extended in this case, see e.g. [this question](http://stackoverflow.com/questions/2784262/does-a-const-reference-prolong-the-life-of-a-temporary). – n. m. could be an AI Feb 16 '14 at 08:13
  • This is probably implementation specific, but see https://ideone.com/7ZI6OH for what might happen: &a in main() is not equal to &a in function(). – Rory Yorke Feb 16 '14 at 08:23
  • @RoryYorke That's expected. `a` is bound to a *temporary*, not to the static variable from the function. – n. m. could be an AI Feb 16 '14 at 08:26
1

Question: Does there exist some way to catch this type of error at compile time while keeping the possibility to write this?

Marking your "B from A" constructor as explicit:

explicit B(const A& a) { /*...*/ }

will prevent the compiler from using it to perform an automatic conversion. See this question for more information.

Community
  • 1
  • 1
Martin J.
  • 5,028
  • 4
  • 24
  • 41