对于不同的构造
的命令行参数让我们假设我有一些C++抽象类和它的所有继承类有不同的构造函数:对于不同的构造
class Abstract{
//don't worry, there is some pure virtual method here
}
class A : public Abstract {
public:
A (int Afirst, std::string Asecond, int Athird) {...}
...
}
class B : public Abstract {
public
B (double Bfirst, std::int Bsecond) {...}
...
}
class C : public Abstract {
public
C (std::string Cfirst, double Csecond, int Cthird, float Cfourth) {...}
}
正如你可以看到,所有的继承类有(可能)不同的构造。
现在,我想编写一个通用main()
,是这样的:
int main (int argc, char *argv[]){
if(argc < 2){
std::cerr<<"Too few arguments!"<<std::endl;
exit(1);
}
std::string type = argv[1];
Abstract *abs;
if(!type.compare("A"){
if(argc < 5){
std::cerr<<"Too few arguments for A!"<<std::endl;
exit(1);
}
abs = new A(atoi(argv[2]), argv[3], argv[4]);
}
//similar for B, C, D
}
我不知道是否有做到这一点,例如直接char *argv[]
传递给每一个构造函数,使里面的所有检查一个最好的方法构造函数(并最终抛出异常,如描述here)。
你可以做这样的事情是通用:
// functions to convert const char* to given type
template <typename T> T To(const char*);
template <> int To(const char* s) { return atoi(s); }
template <> const char* To(const char* s) { return s; }
template <> std::string To(const char* s) { return s; }
// ...
// Your classes:
struct Abstract { virtual ~Abstract() = default; };
struct A : Abstract { A (int, std::string, int) {}};
struct B : Abstract { B (int, int) {}};
// ...
namespace detail
{
// Helper functions for the factory.
template <typename T, typename Tuple, std::size_t... Is>
std::unique_ptr<Abstract> make_abstract(const char*argv[], std::index_sequence<Is...>)
{
return std::make_unique<T>(To<std::tuple_element_t<Is, Tuple>>(argv[2 + Is])...);
}
template <typename T, typename Tuple>
std::unique_ptr<Abstract> make_abstract(int argc, const char*argv[])
{
constexpr int tuple_size = std::tuple_size<Tuple>::value;
if (argc < tuple_size) {
throw std::runtime_error("Too few arguments");
}
return make_abstract<T, Tuple>(argv, std::make_index_sequence<tuple_size>());
}
}
// The public factory
std::unique_ptr<Abstract> make_abstract(int argc, const char*argv[])
{
if (argc == 1) {
return nullptr;
}
const std::string name = argv[1];
if (name == "A") {
return detail::make_abstract<A, std::tuple<int, std::string, int>>(argc, argv);
} else if (name == "B") {
return detail::make_abstract<B, std::tuple<int, int>>(argc, argv);
}
// ...
return nullptr;
}
我的编辑怎么样?我把它从[这里](http://stackoverflow.com/a/1640765/4480180) – justHelloWorld
@justHelloWorld:这可能是可能的,但我更喜欢保留我的样本,因为它是OP用于转换,让普通字符串的空格。另外,我认为它展示了如何将其他类型扩展为'enum'。 – Jarod42
你能解释一下代码吗?这有点先进的我认为 – justHelloWorld
您将无法脱身不得不检查参数恕我直言匹配给定构造的,但我不会有污染类检查代码。我会写一个带'argc'和'argv'的工厂函数并返回适当类的实例。这将保持包含的检查代码。 – Unimportant