提问人:Namal 提问时间:4/25/2023 最后编辑:Namal 更新时间:4/25/2023 访问量:60
非虚拟接口中具有链式方法的 getter
A getter in a non-virtual interface with a chained method
问:
我有以下接口,可以返回一个映射,其中包含一对 int 和 string 作为键和字符串作为值。
class Foo {
public:
virtual ~Foo() = default;
Foo& operator=( const Foo& ) = delete;
std::map<std::pair<unsigned int, std::string>, std::string> save_to_map(const std::string filename) {return getRecord(filename);}
private:
virtual std::map<std::pair<unsigned int, std::string>, std::string> getRecord(const std::string filename) = 0;
};
class Bar final : public Foo {
public:
Bar() = default;
private:
std::map<std::pair<unsigned int, std::string>, std::string> getRecord(const std::string filename) override {
std::map<std::pair<unsigned int, std::string>, std::string> fullRecord;
fullRecord[std::make_pair(0, "A")] = "text";
fullRecord[std::make_pair(0, "B")] = "2";
fullRecord[std::make_pair(0, "C")] = "3.41";
return fullRecord;
}
};
我正在使用工厂函数初始化对象,并且可以以通常的方式访问映射的值。
std::unique_ptr<Foo > fac_func(){
auto dbi = std::make_unique<Bar>();
return dbi;
}
int main(){
auto p = fac_func();
auto m = p ->save_to_map("path\to\file");
std::cout<<m[std::make_pair(0, "A")]<<'\n';
std::cout<<m.at(std::make_pair(0, "B"))<<'\n';
}
现在,我想通过键的两个值访问值,并添加一个链接方法,如果可能的话,将值转换为标准类型的 int、double 或字符串。但在我的脑海中,我没有掌握实现这一目标的最佳实践。比如,作为私人会员,我是否需要额外的地图,或者我是否需要一种特殊的工厂功能?最后,它应该是这样的:
std::string s = p -> Get(0, "A").AsString();
int i = p -> Get(0, "B").AsInt();
编辑:根据要求,我正在添加我删除的其他代码,以便有一个最小的示例。所以 getRecord 看起来像这样:
std::map<std::pair<unsigned int, std::string>, std::string> getRecord(const std::string tableName) override {
std::map<std::pair<unsigned int, std::string>, std::string> fullRecord;
column_names = get_column_names(tableName);
std::string sqlExpr = "Select * from " + tableName;
tableSelect(fullRecord, sqlExpr, column_names);
return fullRecord;
}
这是 tableSelect
void SqliteDB :: tableSelect(std::map<std::pair<unsigned int, std::string>, std::string> &record_map, const std::string sqlExpr, const std::vector<std::string> ¶ms){
unsigned int columnCount;
const unsigned char *columnText;
sqlite3_stmt *stmt;
int rc = sqlite3_prepare_v2(sqlDb, sqlExpr.c_str(), -1, &stmt, NULL);
if(!params.empty()){
for(size_t i = 0; i<params.size(); ++i){
sqlite3_bind_text(stmt, i+1, params[i].c_str(), params[i].length(), SQLITE_TRANSIENT);
}
}
if (rc != SQLITE_OK) {
std::cout<<"error: "<<sqlite3_errmsg(sqlDb)<<'\n';
return;
}
for(size_t j = 0; sqlite3_step(stmt) == SQLITE_ROW; ++j) {
columnCount = sqlite3_data_count(stmt);
for(size_t i = 0; i<columnCount; ++i){
columnText = sqlite3_column_text(stmt, i);
if(columnText != NULL){
record_map[std::make_pair(j, params[i])] = reinterpret_cast<const char*>(columnText);
}
}
}
sqlite3_finalize(stmt);
}
答:
0赞
fana
4/25/2023
#1
准备一个具有方法、等的类。AsString
AsInt
class StrUtil
{
private:
const std::string &m_rStr;
public:
StrUtil( const std::string &Str ) : m_rStr{Str} {}
const std::string &AsString() const { return m_rStr; }
int AsInt() const { return std::stoi( m_rStr ); }
};
接下来,创建类似 map 的类,该类提供方法返回而不是原始 。StrUtil
std::string
class MapLike
{
public:
MapLike()
{//This is test code
m_Map[ std::make_pair( 0, "A") ] = "text";
m_Map[ std::make_pair( 0, "B") ] = "2";
m_Map[ std::make_pair( 0, "C") ] = "3.14";
}
public:
StrUtil operator()( unsigned int Key1, const std::string &Key2 ) const
{
auto iElem = m_Map.find( std::make_pair(Key1,Key2) );
return StrUtil( iElem!=m_Map.end() ? iElem->second : "" );
}
private:
std::map< std::pair<unsigned int, std::string>, std::string > m_Map;
};
//test
int main()
{
MapLike M;
std::cout << M( 0, "A" ).AsString() << '\n';
std::cout << M( 0, "B" ).AsInt() << '\n';
return 0;
}
评论
0赞
Namal
4/25/2023
这似乎不适用于 AsInt,因为它崩溃了。
0赞
fana
4/26/2023
是的,首先,“解析为整数”之类的过程不能适用于所有任意字符串。这个示例代码不处理这样的点,因为我认为这样的点不是这个问题的重点
评论
map
fac_func
p->Get
Foo
Bar
tableName
getRecord