我们说我们有以下两个班级
class Base {
public:
virtual ~Base();
virtual void op(string& s1) = 0;
};
class Derived1 : public Base {
public:
virtual void op(string& s1) override;
};
到目前为止,这么好。现在,需要一个新的要求
创建Derived2类,但是这个类需要2个字符串
作为op虚函数中的args。当然,如果我添加功能op
在Derived2中有2个字符串作为输入,它被重载而不是覆盖。
所以,我必须做一些像 -
class Base {
public:
virtual ~Base();
virtual void op(string& s1) {}
virtual void op(string& s1, string& s2) {}
};
class Derived1 : public Base {
public:
virtual void op(string& s1) override;
};
class Derived2 : public Base {
public:
virtual void op(string& s1, string& s2) override;
};
这样可行,但我被迫在Base类中添加第二个op函数。 此外,Base类函数现在不是纯虚拟的,这是 否则派生类需要实现不必要的 操作功能。这对我来说似乎有些愚蠢。
现在,如果新要求导致我们创建Derived3,则需要创建Derived3 op函数的不同参数集,我们需要再添加一个 基类中的op函数。理想情况下,基类不应该改变 有人添加了一个新的派生类。
我确信有更好的方法可以做到这一点。很确定有一个 设计模式,因为这似乎是一个常见的问题和 必须已经解决了。
有什么建议吗?
谢谢, Amarnath
答案 0 :(得分:0)
如果你有多个派生类并不“行为”相同(例如,对于不同的派生类有不同数量的参数),你有两个选择(有一些变化):
在基类中为所有变体实现虚函数。
你的班级hieararchy不是“干净”,你可能需要“知道”在某些情况下它是哪种类型。使用dynamic_cast
(或您自己的类型检测机制,如在LLVM项目中,具有llvm::dyn_cast
)
考虑一下:
vector<Base*> v;
... insert derived types in v ...
for(auto i : v)
{
v->op( ??? )
}
如果op
是1,2或3个参数,代码如何知道?它不能,对吧?因此,您的选择是询问班级op
需要多少参数,并始终使用相同的数字(例如,op("abc", "", "");
将用于Derived1
,op("abc", "def", "");
Derived2
已op("abc", "def", "ghi");
,Derived3
为class Base {
public:
virtual ~Base();
virtual void op(string& s1) = 0;
virtual void op(string& s1, string &s2) = 0;
... for as many string arguments you need ...
virtual int num_strings() { return 0; }
};
class Derived1 : public Base {
public:
virtual void op(string& s1) override;
virtual int num_strings() override { return 1; }
};
class Derived2 : public Base {
public:
virtual void op(string& s1, string& s2) override;
virtual int num_strings() override { return 2; }
};
。
或者你可能有类似的东西:
for(auto i : v)
{
switch(v->num_strings())
{
case 1:
v->op(s1);
break;
case 2:
v->op(s1, s2);
break;
default:
... some handling of unknown number ....
}
}
现在我们可以实现我们的通用(-ish)循环:
llvm::dyn_cast
这里的关键是,如果你要对从同一个基类派生的所有对象“做”同样的事情,他们必须拥有相同的接口。
在我拥有的编译器项目中,我在需要时使用if
,因为基类有许多泛型操作,但并非ALL操作在所有派生类上都可用,因为这会使基类成为基类拥有大量完全没用的成员函数 - for
不必具有与if
循环相同的操作,并且赋值不需要for
的任何内容。需要1}}或op(vector<string>& sv)
循环。
imap <LeftMouse>i
而不是1,2,3或n个参数。
与许多事情一样,如果不进一步了解确切的问题,正确的解决方案并不总是很明确。
答案 1 :(得分:0)
从Mats回答并使用c ++初始化列表构造函数的正确方法可以是(在调用op functon时注意括号{}):
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Base {
public:
virtual ~Base() { };
virtual void op(const std::vector<string>& s1) {std::cout<<"Base..."<<s1.at(0)<<std::endl;}
// virtual void op(const stdstring& s1, const string& s2) {std::cout<<"Base..."<<s1<<" "<<s2<<std::endl;}
};
class Derived1 : public Base {
public:
virtual void op(const std::vector<string>& s1) override {std::cout<<"Derived1..."<<s1.at(0)<<std::endl;}
};
class Derived2 : public Base {
public:
virtual void op(const std::vector<string>& s1) {std::cout<<"Derived2..."<<s1.at(0)<<std::endl;}
};
int main()
{
Base *ptr= new Derived2();
ptr->op({std::string("Test1"),std::string("Test2")});
}