假设我有一个基类A,我希望有一个方法getName,可以接受整数或字符串作为参数。所以我创建了:
virtual string getName(int index) = 0;
virtual string getName(string key) = 0;
现在,我想创建两个不同的子类B和C.B只需要getName(int index)
而C只需要getName(string key)
。
但是,如果我不覆盖两个子类中的两个方法,我会收到错误。但是如果我这样做,那么B和C将有一个空方法,因为它们不需要getName
的其他情况
我该如何克服这个问题?
答案 0 :(得分:3)
听起来你真的想要两个不同的界面:一个支持getName(int)
,一个支持getName(string)
。
struct GetNameInt {
virtual string getName(int index) = 0;
};
struct GetNameStr {
virtual string getName(string key) = 0;
};
struct B : GetNameInt { /* ... */ };
struct C : GetNameStr { /* ... */ };
如果真的需要一个具有相同界面的基类,并且仅在运行时知道您是否需要{{1}或者string
,您可能想要使用int
:
std::variant
答案 1 :(得分:1)
您未正确使用继承。我强烈建议您详细了解SOLID principles。
您需要将A类拆分为两个类(接口) - Aa和Ab,其中Aa将保存getName(int index)并且将具有getName(字符串键),如:
class A {
//does not define neither of the getName methods
}
class Aa {
virtual string getName(int index) = 0;
}
class Ab {
virtual string getName(string key) = 0;
}
class B : A, Aa {
//inherits from A and defines string getName(int index)
}
class C : A, Ab {
//inherits from A and defines string getName(string key)
}
答案 2 :(得分:0)
好的,我最好能够在B和C之间保持一个共同的父级,同时仍然保留一些类型安全性和编译时间检查:
struct CommonA //protect this if possible
{
template<class type>
string getGenericName(type index);
virtual ~CommonA() {}
};
template<class indexType>
struct A : CommonA
{
virtual string getName(indexType index) = 0;
};
struct B : A<int>
{
string getName(int index) override {cout << index << "\n"; }
};
struct C : A<string>
{
string getName(string index) override {cout << index << "\n"; }
};
template<class type>
string CommonA::getGenericName(type index)
{
cout << "generic call: \n";
return dynamic_cast<A<type>*>(this)->getName(index);
}
int main()
{
CommonA b = B();
CommonA c = C();
b.getGenericName(1);
c.getGenericName(string("hello world"));
}
请注意,此解决方案不是标准的OOP解决方案,而是模板解决方案。
编辑:我的模板A&lt;&gt; class与Vittorio Romeo的解决方案相同,使用模板而不是名字粘贴(名字粘贴是邪恶的)
答案 3 :(得分:-2)
简单地说,不要让它们变成纯虚拟的,而只是虚拟的:
struct Blub
{
virtual void do1() {} // default definition
virtual void do2() = 0; //has to be overridden
};