3
$\begingroup$

I have read the following artice that defines the term "constructor anomaly":

Cohen, Tal, and Joseph Gil. "Better Construction with Factories." journal of object technology 6.6 (2007): 103-123. http://www.jot.fm/issues/issue_2007_07/article3/

Where can I find examples and references on constructor anomalies? (also in the context of multiplie inheritance)

Are constructor anomalies always due to a method call in the constructor or is it possiple to construct an example without method calls in the constructor?

$\endgroup$

1 Answer 1

3
$\begingroup$

"Constructor anomaly" is not a bug or anything; it is simply an anomaly on the classification of constructor functions. ie. constructor functions are different from member functions in the following ways.

Anomalous classifications:

  • While most member functions require an instance and work on an instance, a constructor does not require an instance, but still works on an instance:

      f.bar(); // instance of f, can call bar(). bar() does stuff to/with f.
    
      new F(); // no instance, yet called F::F(). Yet F::F() does works on an instance.
    
  • Most member functions can replace or extend their base-class functions with the same name; that is, a member function can entirely override a base-function (replacement), ... or ... it can override, and call the base function as well (extension). However, the constructor (in these languages) must extend, that is, call the base-class constructor first. (This is to delegate the base-class's construction to the base-class, first, and then construct the derived class):

    struct F{
        F(){/*stuff*/}
        virtual void bar(){/*stuff*/}
        virtual void baz(){/*stuff*/}
    };
    struct G : public F{
        virtual void bar()
        {
          //Do stuff
          F::bar(); // extend F::bar()
          //Do more stuff
        }
        virtual void baz()
        {
          //Do stuff
          //Do more stuff
          //No call to F::baz(), replaced it
        }
        G::G(){
          //this MUST extend F::F(); in C++ F() is called implicitly in this case.
          //However, if F() takes parameters, it must be called explicitly
        }
    };
    
    
  • Most member functions can be dynamically bounded; that is, you never know if a (virtual) function F* f; f->bar() is calling F::bar() or if f is a type that derived from F; and thus a different bar is being called. However, constructors are always static, you must know exactly which class you are creating when you create it:

    H* h = get_h();
    h->bar(); // this function can be H::bar(), or anything defined in the virtual table; hence it is dynamic; h can be any derivative of H, overriding H::bar().
    
    
    F* f = new F(); // the call to F::F() MUST be (statically) linked to F(), not a derivative of F
    
$\endgroup$
4
  • $\begingroup$ great answer! do you know an example where calling bar or baz in the constructor (say in F) can lead to a NullPointer-Exception? Say G introduces a new field "person" of Type Person. The repaced method baz in G accesses this field and assumes this field is initialised with an instanciated Object. The G constructor is called and at the beginning the F constructor is called, this calls baz, this accesses the new field allthough the G constructor has not yet been fully executed to initialize the "person" field and thus causing a NullPointer Exception. (I think in Java terms but hope it is clear) $\endgroup$
    – mrsteve
    Oct 28, 2013 at 18:14
  • $\begingroup$ @mrsteve I am pretty sure calling virtual functions in a ctor is a no-no in C++ for this very reason. $\endgroup$
    – Realz Slaw
    Oct 28, 2013 at 22:58
  • $\begingroup$ I tested the mentioned example in Java and indeed a NullPointer exception is thrown. So in C++ there is no Problem but in Java it is the case! Thank you for your answer it helped me to understand the topic! $\endgroup$
    – mrsteve
    Oct 29, 2013 at 6:03
  • $\begingroup$ @mrsteve in C++ there is a problem; see Do not invoke virtual functions from constructors or destructors. The only difference is, there are no NullPointerExceptions in C++, and it will happily keep running your program and randomly crash if it wants to (consequence of undefined behavior). $\endgroup$
    – Realz Slaw
    Oct 29, 2013 at 13:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.