Kira Yamato wrote:
On 2008-02-16 14:25:25 -0500, junw2000@gmail.com said:
Is there any problem if call virtual function in constructor? For
example:
class A
{
public:
A()
{
setvalue();
}
setvalue()
{
data = getnumber();
}
print() { cout << data << endl;
private:
virtual int getnumber() {return 100;}
int data;
}
class B : public A
{
public:
B() { }
private:
virtual int getnumber() {return 22222;}
}
int main()
{
A test1;
test1.print() ;
B test2;
test2.print() ;
}
Technically, it's perfectly fine to call virtual functions in the
constructor as long as you understand that it will not invoke any
possible derived-class's overriding version of the same method. Also,
your compiler will complain if you're calling a pure virtual function.
However, semantically speaking, it seems weird why you would want to
invoke a method that your object wishes to override. I can't pinpoint
it yet, but it seems like a bad design. Sorry for being so vague.
Perhaps an expert can help point out the problem in a clear way.
It is sometimes useful to initialize different classes of a hierarchy
with the derived class-dependent code and then return back to the base
class constructor to execute some of its code again to avoid
duplicating that latter common code.
For example (this code will not work in C++ but the analogous code will
work in other programming languages (e.g. Java) and I do not see any
fundamental design flaws in this code).:
typedef std::map<std::string> ConnectionParameters;
class FooConnection {
protected:
virtual void init(const ConnectionParameters &pars) = 0;
public:
FooConnection(const ConnectionParameters &pars) {
init(pars);
validateConnection();
}
private:
void validateConnection()
throw(FooConnectionException /*defined elsewhere*/)
{
/* perform some uniform validation here, for example
some select from "FOO_MAIN_TABLE" */
}
};
class OracleFooConnection : public FooConnection {
protected:
void init(const ConnectionParameters &pars) {
// .. do Oracle-specific initialization
}
};
class MySqlFooConnection : public FooConnection {
protected:
void init(const ConnectionParameters & pars) {
// .. do MySql-specific initialization
}
};
This way, you can perform all validation in the constructor, that is,
according to the best practices, and without duplicating the common
validation code in the derived class.
Interesting example. However, I would like to propose that in any case
pattern should be considered.
derived-class-specific validation code. This way avoids the need to