2011-11-03 131 views
2

我想提出一个包装为我用的数据库,采用波科::数据库:: ODBCC++类成员初始化(POCO)

正常的代码应该是这样的:

Poco::Data::ODBC::Connector::registerConnector(); 
Session ses("ODBC", "DSN=mytest;Uid=mytest;Pwd=mytest"); 
bool bConnected = ses.isConnected(); 
Statement select(ses); 
select << "SELECT firstname FROM Patients", range(0, 10); 
RecordSet rs(select); 
while (!select.done()) 
{ 
    select.execute(); 
    bool more = rs.moveFirst(); 
    while (more) 
    { 
     for (std::size_t col = 0; col < rs.columnCount(); ++col) 
     { 
      std::cout << rs[col].convert<std::string>() << " "; 
     } 
     std::cout << std::endl; 
     more = rs.moveNext(); 
    } 
} 

Poco::Data::ODBC::Connector::unregisterConnector(); 

这工作得很好。

现在对于我的课

class database{ 
    Session ses; //Since this is needed all for all the queries. 
    public: 
    database():ses("ODBC", "DSN=name;uid=user;pwd=pass"){ 
    } 
};//end class 

我如何的ses

初始化调用之前调用Poco::Data::ODBC::Connector::registerConnector()我试图

database():Poco::Data::ODBC::Connector::registerConnector(),ses("ODBC", "DSN=name;uid=user;pwd=pass"){ 
} 

但这并不适用。它提供了错误

'registerConnector' : is not a member of 'Poco::Data::ODBC::Connector'

我应该怎么办呢?

回答

4

要么在database::database()以外,要么使用指向Session而不是成员的指针,并将其分配到构造函数中的堆上。例如:

database::database() 
{ 
    Poco::Data::ODBC::Connector::registerConnector(); 
    ses = new Session("ODBC", "DSN=name;uid=user;pwd=pass"); 
} 

database::~database() 
{ 
    delete ses; 
} 
+0

'ses'用于像'ses <<“SELECT COUNT(*)FROM customer”这样的语句,进入(count),now;',我早些时候试过这种方法,但是这些语句给出了错误。 – Pheonix

+0

'(* ses)<<“SELECT COUNT(*)FROM customer”'将起作用。 或者:Session&sessRef = * ses; sessRef <<“SELECT COUNT(*)FROM customer'如果你觉得它太笨拙 –

+0

谢谢,使用第一个版本 – Pheonix

0

看起来像registerConnector是一项免费功能。要调用初始化列表内的其他功能,您可以用逗号:

database() 
    : ses(
     (Poco::Data::ODBC::Connector::registerConnector(), "ODBC") 
     , "DSN=name;uid=user;pwd=pass" 
    ) 
{...} 

的内置逗号运算两个表达式,并返回第二个结果。

或者,您可以创建一个处理registerConnector()类的自定义类,并将其放置在类ses之前的类中,以使其构造将在ses之前发生。

+0

编译器说'registerConnector'在这种情况下是不确定的 – Pheonix

+0

@Pheonix:你应该 - 当然 - 在实际代码中使用全名,所以它实际上应该是'Poco :: Data :: ODBC :: Connector :: registerConnector() –

+0

我也试过了,错误表示参数列表不匹配 – Pheonix

1

要直接实现这种功能,你写周围的registerConnector功能的RAII风格的包装对象:

class wrapper { 
public: 
    wrapper() { 
     Poco::Data::ODBC::Connector::registerConnector(); 
    } 
    ~wrapper() { 
     Poco::Data::ODBC::Connector::unregisterConnector(); 
    } 
} 

所以,你现在可以做的:

class database{ 
    Wrapper wrap; 
    Session ses; //Since this is needed all for all the queries. 
    public: 
    database() : wrap(), ses("ODBC", "DSN=name;uid=user;pwd=pass"){ 
    } 
}; 

不过,我不我认为这是一个很好的设计;它留下悬而未决的问题:

  1. 你为什么在database包装初始化数据库子系统?也许它应该作为程序初始化例程的一部分来完成?
  2. 如果同时使用多个database对象,会发生什么情况?注册/取消注册会导致问题;如上所述做init不会。
+0

我想你会想在之前声明Wrapper会话,以便它首先被实例化/初始化。构造函数初始化列表不会控制这个(至少不会在gcc中会警告这个代码)。 –

+1

'ses'会先被初始化。初始化列表中的评估顺序是成员定义的顺序,而不是它们在初始化列表中调用的顺序。这是因为需要确保所有构造函数中的单个顺序,以便析构函数能够以相反顺序破坏事物。 –

+0

@Jon:好的,我做了这个,但是这似乎并不能解决问题,不知怎的,换行之前不会调用wrap(就像上面提到的Nathan可能)。 对于你的问题,我认为它不是很好的设计,但我不是非常有经验的+/-各种设计。我还是个学生。 1.我想它应该与程序init例程,我试图保持数据库部分分开。 2.由于我有一个单一的数据库进行查询,我计划一次只保留一个对象,虽然我看到你指向多个数据库。 谢谢 – Pheonix