这是我的问题,我想调用我的一个对象的getter / setter,但不是直接调用,我想通过使用std :: string来实现。
我找到了this,但它不适用于我的情况我认为这是因为我的函数没有在我的main方法中定义,而是在我的方形类中。此外,我的函数并非都以与void(std :: string)相同的方式定义std :: string()void(int)......
这是一个想要做的事情的例子。
我的对象广场
#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 :: string调用我的square.setName(),而不是在我的main中写入这个square.setName。
答案 0 :(得分:1)
要根据字符串调用函数,您有一些选择。在列出选择之前,请在互联网上搜索“C ++工厂设计模式”。
可能还有其他方法,但我想到了上述方法。
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
数据结构;它不能直接从可执行代码访问或加载。
同样,所有功能必须具有相同的签名。
这里的想法是拥有一个函数指针数组或一个带有text&amp;的结构数组。函数指针。创建一个 hash 函数,该函数根据名称字符串生成唯一的数组索引。使用索引从数组中获取函数指针,然后通过函数指针执行该函数。
答案 1 :(得分:0)
您可以使用多种解决方案。您基本上想要解析用户输入以填充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,您可以省略前三个结构,以帮助我使用interger_sequence
在参数列表中扩展我的元组