gpt4 book ai didi

C++ 实现类根据它使用的字符串构造另一个类的实例

转载 作者:行者123 更新时间:2023-12-02 15:57:20 25 4
gpt4 key购买 nike

我需要实现一个抽象类、它的三个具体子类,该类的目标是创建这三个类实例之一和三个类的最后一个类执行器。要求是 c++98,而不是使用 if/elseif/else 来构造类实例,就像我在 Maker 类方法 make Form 中所做的那样。 if/elseif/else 我需要避免什么机制?

例如:

测试.h

#ifndef TEST_H
#define TEST_H
#include <iostream>

class Executor {
private:
const std::string name;
public:
Executor(const std::string &name = "") {};

const std::string getname() const {return name;}
};

class BForm {
private:
const std::string _name;
public:
BForm(const std::string &name = "") : _name(name) {};
virtual ~BForm() {};

virtual void execute(const Executor &src) = 0;

const std::string getname() {return _name;}
virtual const std::string gettarget() = 0;
};

class Form1 : public BForm{
private:
std::string _target;
public:
Form1(const std::string &target = "") : BForm("form1"), _target(target) {};
virtual ~Form1() {};

virtual void execute(const Executor &src) {
std::cout << src.getname() << " exec form1 target:" << _target << std::endl;
}

virtual const std::string gettarget() {return _target;}
};

class Form2 : public BForm {
private:
std::string _target;
public:
Form2(const std::string &target = "") : BForm("form2"), _target(target) {};
virtual ~Form2() {};

virtual void execute(const Executor &src) {
std::cout << src.getname() << " exec form2 target:" << _target << std::endl;
};
virtual const std::string gettarget() {return _target;}
};

class Form3 : public BForm {
private:
std::string _target;
public:
Form3(const std::string &target = "") : BForm("form3"), _target(target) {};
virtual ~Form3() {};

virtual void execute(const Executor &src) {
std::cout << src.getname() << " exec form3 target:" << _target << std::endl;
};
virtual const std::string gettarget() {return _target;}
};

class Maker {
public:
BForm *makeForm(const std::string &name, const std::string &target)
{
/* need to avoid */
if (name == "form1")
return new Form1(target);
else if (name == "form2")
return new Form2(target);
else
return new Form3(target);
}
};

#endif

main.cpp

#include "test.h"

int main() {
Maker maker;
BForm *form;
Executor exec("executor");

form = maker.makeForm("form1", "A");
std::cout << form->getname() << " " << form->gettarget() << std::endl;
form->execute(exec);
delete form;
return (0);
}

最佳答案

你可以定义一个指向函数的指针,然后使用从字符串到这个类型(指向函数的指针)的映射。然后使用带有索引器语法的参数来访问指向函数的正确指针。

这是一个例子:

#include <iostream>
#include <map>

// The class definitions with a virtual function hello() common to all
class Base { public: virtual void hello() = 0; };
class Derived1 : public Base { public: void hello() { std::cout << "Derived1"; } };
class Derived2 : public Base { public: void hello() { std::cout << "Derived2"; } };

// The object making functions
Base* Maker1() { return new Derived1; }
Base* Maker2() { return new Derived2; }

int main()
{
// In C++98, without auto, it's worthwhile to typedef complicated types.
// The first one is a function type returning a pointer to Base...
typedef Base* MakerT();
// ... the second one is a map type projecting strings to such function pointers
typedef std::map<std::string, MakerT*> StrToMakerT;

/// The actual map projecting strings to maker function pointers
StrToMakerT strToMaker;
// Fill the map
strToMaker["D1"] = &Maker1;
strToMaker["D2"] = &Maker2;

// user input
std::string choice;

// as long as output works, input works, and the user didn't say "Q":
while (std::cout << "Please input 'D1' or 'D2' or 'Q' for quit: "
&& std::cin >> choice
&& choice != "Q")
{
// Prevent adding new entries to the map foir unknown strings
if (strToMaker.find(choice) != strToMaker.end())
{
// Simply look the function up again, the iterator type is too
// cumbersome to write in C++98
Base* b = (*strToMaker[choice])();
b->hello();
std::cout << '\n';
delete b;
}
else
{
std::cout << "Didn't find your choice, try again.\n";
}
}
std::cout << "Thank you, good bye\n";
}

关于C++ 实现类根据它使用的字符串构造另一个类的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71286460/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com