如何使用std::字符串从对象中调用函数
How to call a function from an object with a std::string
这是我的问题,我想调用我的一个对象的getters/ssetter,但不是直接调用,我想通过使用std::字符串来实现。
我发现了这个,但它对我的情况不起作用,我想这是因为我的函数不是在我的主方法中定义的,而是在我的平方类中定义的。此外,我的函数的定义方式也不完全相同——有void(std::string(std::string((void(int(。。。
这是a想做什么的一个例子。
我的目标正方形
#include <map>
#include <functional>
#include <string>
class Square{
private:
std::string name;
int width;
float happinessPoint; //extremly important for your square.
public:
void setName(std::string);
void setWidth(int);
void setHappinessPoint(float);
std::string getName()
int getWidth()
float getHappinnessPoint()
}
和我的主要
#include "Square.h/cpp"
int main(){
Square square = Square("Roger",2,3.5);
// here in my magicalFunction I ask to the users the new values for my square (all in std::string for now)
vector <std::string> newValueForSquare = magicalFunction();
for (unsigned int i=0; i < newValueForSquare.size(), i++){
//here I have a function which tell me if my std::string
// is in fact a float or an int
// and I would like to call each of my setters one by one to
// sets my Square to some value I asked to the user before all that.
// something like that:
// someFunction("setName","Henry")
}}
我希望我已经清楚了,很难解释一些你不知道该怎么做的事情。如果你想让我更具体地告诉我,我会尽我所能。
编辑:例如,我想用str::字符串调用我的square.setName((,而不在main中写入这个square.setRame。
要根据字符串调用函数,您有一些选择。在我列出选择之前,请在网上搜索"C++工厂设计模式"。
- If else梯子
- 查阅表格
- 映射/关联阵列
- 哈希表
可能还有其他方法,但以上的方法会浮现在脑海中。
if else梯形图(又名switch
(
此方法的问题在于switch
语句既不能处理字符串也不能处理文本。因此,您必须满足if
语句:
if (string == "Roger")
{
Process_Roger();
}
else if (string == "Felicity")
{
Process_Felicity();
}
else
{
Display_Error_Message();
}
每当需要添加新字符串时,都必须向梯形图中添加另一个"else-if"语句。你不仅要更改代码,还要重新测试
查阅表格
您需要了解函数指针,了解此技术和映射技术。将此视为先决条件。
使用一种将文本字符串映射到函数指针的结构:
struct Text_Function_Pointer
{
const char * name;
Function_Pointer p_function;
};
static const Text_Function_Pointer table[] =
{
{"Larry", Process_Larry},
{"Felicity", Process_Felicity},
};
static const unsigned int table_size =
sizeof(table) / sizeof(table[0]);
//...
for (unsigned int i = 0; i < table_size; ++i)
{
if (search_name == table[i].name)
{
// Execute the processing function.
table[i].p_function(search_name);
break;
}
}
此技术的一个问题是,所有函数指针都必须具有相同的签名。地图也是如此。
一个很好的特性是表中的数据是恒定的,所以它可以放在只读存储器中。
此外,要添加更多关联,请在表中添加一个条目。搜索/处理功能没有改变,因此不需要再次测试。
映射/关联阵列
先决条件:函数指针
声明一个std::map<std::string, Function_Pointer_Type>
。将您的姓名和功能添加到地图中:
std::map<std::string, Function_Pointer_Type> dispatch_table;
dispatch_table["Roger"] = Process_Roger;
dispatch_table["Felicity"] = Process_Felicity;
dispatch_table["Larry"] = Process_Larry;
//...
// Execute appropriate processing function:
(dispatch_table[search_name])();
该方法的一个问题是std::map
数据结构需要初始化;它不能直接访问或从可执行代码加载。
同样,所有函数都必须具有相同的签名。
哈希表
这里的想法是拥有一个函数指针数组或一个具有文本&函数指针。创建一个散列函数,该函数基于名称字符串生成唯一的数组索引。使用索引从数组中获取函数指针,然后通过函数指针执行函数。
您可以使用多种解决方案。您基本上想要解析用户输入来填充Square类属性。一种方法是使用std::stoi函数族:
std::vector<string> values { "Roger", "2", "3.5" };
std::string name = values[0]; // No problem, two strings
int width = std::stoi(values[1]); // stoi = stringToInt
float happiness = std::stof(values[2]); // stof = stringToFloat
我不知道你为什么需要for循环,除非你的问题中有我不理解的地方。我会相应地更新我的答案。
更新1
在阅读了其他答案后,我想对你的问题提出我的解决方案。正如我在评论中多次指出的,这不是一个简单的答案
我需要这样一个类来编写一个通用测试引擎,这就是我使用的代码。它可以很好地与任何类型的函数配合使用(除了返回类型为void的例程——不过,一个简单的模板专用化可以解决这个问题(
# include <functional>
# include <tuple>
template<int ...>
struct seq
{
};
template<int N, int ...S>
struct gens : gens<N - 1, N - 1, S...>
{
};
template<int ...S>
struct gens<0, S...>
{
typedef seq<S...> type;
};
struct callable_base
{
virtual void operator()() = 0;
virtual ~callable_base()
{ }
};
class Task
{
private:
template<class RT, class Functor, class ...Args>
struct functor : public callable_base
{
functor(RT& result, Functor func, Args ...args)
: _ret(result)
{
_func = func;
_args = std::make_tuple(args...);
}
void operator()()
{
_ret = call(typename gens<sizeof...(Args)>::type());
}
template<int ...S>
RT call(seq<S...>)
{
return (_func(std::get<S>(_args)...));
}
private:
std::function<RT(Args...)> _func;
std::tuple<Args...> _args;
RT& _ret;
};
public:
Task()
{
_functor = nullptr;
}
template<class RT, class Functor, class ...Args>
Task(RT& result, Functor func, Args... args)
{
_functor = new functor<RT, Functor, Args...>(result, func, args...);
}
void operator()()
{
(*_functor)();
}
~Task()
{
delete _functor;
}
private:
callable_base *_functor;
};
此代码背后的想法是在内部类Task::functor中隐藏函数签名,并在传递给Task(…(构造函数的第一个参数中获取返回值。我首先给出这段代码是因为我认为它可能会帮助一些人,但也因为我认为这是解决您问题的一个优雅的解决方案。请记住,要理解大部分代码,您需要扎实的C++知识。如果需要,我将在后续更新中详细介绍代码。
以下是使用方法:
int main()
{
int retVal;
std::string newName;
std::map<std::string, Task *> tasks {
{"setName", new Task(retVal, &Square::setName, &newName)}
...
}
/* Modify the name however you want */
...
tasks["setname"]();
}
当然,整个类可以进行优化,这主要归功于C++14和移动语义、通用引用等等,但我保持了的简单~一个主要问题是,如果在填充任务映射时不知道参数的值,则必须使用指针。我正在开发另一个版本来简化这一方面,但我想向您展示C++的设计并不是为了满足您的要求。也许你来自一个函数或JS世界,在这个世界里,这将是微不足道的x(
更新2
我只是想指出,使用C++14,您可以省略这里的前3个结构,这些结构可以帮助我使用interger_sequence 在参数列表中扩展元组
- 如何用参数值调用函数(仅在运行时已知)
- 从python中调用C++函数并获取返回值
- 当使用通配符和null指针调用函数时,对输出的说明
- 从R调用C++函数并对其进行集成时出错
- 使用QTreeView,如何通过调用函数只突出显示特定的行/列
- 如何在qt中从另一个类调用函数
- 在 COUT 语句中使用 COUT 调用函数
- 如何从线程中的不同模块调用函数?
- C++从函数指针数组调用函数
- 当 A 在 for 循环中调用函数 B 时,如何计算函数 A 的空间复杂度?
- 如何在 C/C++ 中从外部库调用函数
- 如何使用运算符在同一行中多次调用函数
- 是否可以创建一个从不同类调用函数的线程?
- 无法为类成员调用函数
- 如何从另一个标头 c++ 调用函数
- C++有什么方法可以在既不调用函数模板也不提供其模板参数的情况下引用函数模板?
- 如何只允许在调用函数 B 后调用函数 A?
- 我可以这样调用函数吗?
- 如何在 c++ 的类中递归调用函数方法?
- 为什么在指向对象的迭代器上调用函数不允许我更改对象本身?