2009-10-01

protected and private constructor in C++/C# class

1) There exists only one reason to make constructor protected: The class will not be instantiated, but its subclass will be.
Bingo! Abstract class. See the C# example below:


//abstract class, never be created because abstract
//functions is not yet implemented
public abstract class MarkerBase
{
protected MarkerBase( string req_in ) {}
protected abstract int getMarkerID();
}
//subclass implement the abstract function and
//its constructor reuses the protected
//constructor of its abstract parent.

public class MyMarker : MarkerBase
{
public MyMarker(string req_in) : base(req_in){}
protected override int getMarkerID(){return 0;}
}


2) It is really confused that the class constructor is private. It means
that the class never be instantiated. If the class will never be created,
why do we need it?

The answer is a little mysterious: The class can be created only once by itself,
so-called singlton design pattern.

In some resource-related applications, we want to have only single instance for some classes. For example, if we have implemented a class to access a specific database, we want certainly the application has only an unique instance of this class. Otherwise, if multipe instances may write and read the same database, it is hard to control the synchronization. It is the reason why a singlton class has a private construct, which can be called only by itself once and prevent the class being created for several times by the other classes.

See the c++ class below. The class class manages accessement of a sqlite3 database.

class DBReader
{
public:
void insertRecord(const char* sql_in);
void select(const char* sql_in);
private:
sqlite3 * db_;

//for singleton design pattern
public:
static DBReader* getInstance();
private:
static DBReader* pDBReader_;
DBReader();
void databaseError();
};
DBReader* DBReader::pDBReader_ = NULL;
DBReader* DBReader::getInstance()
{
if(pDBReader_ == NULL)
{
pDBReader_ = new DBReader();
}
return pDBReader_;
}
DBReader::DBReader()
:db_(NULL)
{
// Open the database
sqlite3_open("coki.db", &db_);
if( SQLITE_OK!=sqlite3_errcode(db_) )
{
databaseError();
return;
}
}
...

int main()
{
....
//DBReader::getInstance() is the only
//way to get access database.

DBReader::getInstance()-> insertRecoard(sSQL_CM1);
DBReader::getInstance()-> select(sSQL_CM2);
return 0;

2 comments:

  1. hi,

    First of all. Thanks very much for your useful post.

    I just came across your blog and wanted to drop you a note telling you how impressed I

    was with the information you have posted here.

    Please let me introduce you some info related to this post and I hope that it is useful

    for .Net community.

    There is a good C# resource site, Have alook

    http://www.csharptalk.com/2009/09/c-class.html
    http://www.csharptalk.com

    simi

    ReplyDelete