【问题标题】:c++ class member initialization (poco)c++ 类成员初始化(poco)
【发布时间】:2011-11-03 18:46:15
【问题描述】:

我正在使用 Poco::Database::ODBC 为我的数据库制作一个包装器

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

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'

我该怎么做??

【问题讨论】:

    标签: c++ oop class initialization poco-libraries


    【解决方案1】:

    要么在database::database() 之外进行,要么使用指向Session 的指针而不是成员,然后在构造函数内部的堆上分配它。比如:

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

    【讨论】:

    • ses 将用于 ses &lt;&lt; "SELECT COUNT(*) FROM customer", into(count), now; 之类的语句中,我之前尝试过这种方法,但是这些语句给出了错误。
    • (*ses) &lt;&lt; "SELECT COUNT(*) FROM customer" 将工作。或者:Session &amp;sessRef = *ses; sessRef &lt;&lt; "SELECT COUNT(*) FROM customer 如果您觉得它太笨拙。
    • 进一步说明:因为您似乎可以有很多database,但您只想调用一次registerConnector,我认为最好的方法是调用@ 987654330@一次且仅一次在main(),然后使用你原来的代码(成员变量,带初始化列表)。
    【解决方案2】:

    要直接启用这种功能,您可以在 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 不会。

    【讨论】:

    • 我认为你会想要在 Session 之前声明 Wrapper 以便它首先被实例化/初始化。构造函数初始化列表不控制它(至少在 gcc 下不会对此代码发出警告)。
    • ses 将首先被初始化。初始化列表中的求值顺序是定义成员的顺序,而不是初始化列表中调用它们的顺序。这是因为所有构造函数之间需要保证一个单一的顺序,这样析构函数就可以以相反的顺序破坏事物。
    • @Jon: 好的,我做了这个,但这似乎并没有解决问题,在 ses 之前没有调用 wrap (正如上面提到的 Nathan 可能)。对于您的问题,我认为这不是好的设计,但我对各种设计的 +/- 不是很有经验。我还是学生。 1.我想应该是程序初始化例程,我试图将数据库部分分开。 2. 由于我有一个要查询的数据库,我计划一次只保留一个对象,尽管我明白你对多个数据库的看法。谢谢
    • @K-ballo:你当然是完全正确的,谢谢你的问题。编辑修复。
    【解决方案3】:

    看起来registerConnector 是一个免费功能。要调用初始化列表中的其他函数,可以使用逗号运算符:

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

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

    或者,您可以创建一个处理registerConnector() 类的自定义类,并将其放置在ses 之前的类中,这样它的构造就会在ses 之前进行。

    【讨论】:

    • 编译器说 registerConnector 在这种情况下是未定义的。
    • @Pheonix:你当然应该在实际代码中使用全名,所以它实际上应该是Poco::Data::ODBC::Connector::registerConnector()
    • 我也试过了,错误说参数列表不匹配。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-18
    • 2017-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-15
    • 2023-04-08
    相关资源
    最近更新 更多