patternMinor
OOP: exampe and references on constructor anomalies
Viewed 0 times
constructoranomaliesandreferencesexampeoop
Problem
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?
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?
Solution
"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
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
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
Context
StackExchange Computer Science Q#16503, answer score: 3
Revisions (0)
No revisions yet.