假设我有一个带有虚函数Base
的抽象基类doSomething()
有两个派生类,其中一个在doSomething()
中没有参数,而另一个在结构和整数中作为参数。
另一个类(SomeClass)中的函数使用doSomething()
变量调用Base*
。
它还需要传递我为DerivedTwo
提到的参数。
如何在不使用if-else选择原型的情况下在运行时检查对象的类?
谢谢。
class Base {
public:
void virtual doSomething();
}
class DerivedOne : Base {
public:
void doSomething(int a,struct b);
}
class DerivedTwo : Base {
public:
void doSomething();
}
答案 0 :(得分:2)
如果你需要为两个派生类型传递这些变量,只需在任何地方声明它们,如下所示:
class Base {
public:
void virtual doSomething(int a,struct b);
}
class DerivedOne : Base {
public:
void doSomething(int a,struct b);
}
class DerivedTwo : Base {
public:
void doSomething(int a,struct b);
}
如果您需要为一种类型而不是另一种类型使用参数,那么您需要的不是类层次结构。在这种情况下,您需要更详细地阐述您的问题。
答案 1 :(得分:2)
您想要更改派生类中虚拟方法的参数列表。这是不可能做到的。通常,当您发现自己想要这样做时,表明您的类层次结构设计不正确。
解决这个问题的天真尝试通常涉及向基类添加一些东西,这对某些派生类只有意义。这违反了良好设计的原则。
有许多不同的方法可以更恰当地解决这个问题,但很难根据这个人工构建的例子提出建议。
答案 2 :(得分:1)
这样做的一种方法是:
class Base {
public:
Base();
virtual ~Base();
virtual void doSomething();
};
class DerivedOne : public Base {
public:
DerivedOne();
void doSomethingElse(int a,struct b);
};
class DerivedTwo : public Base {
public:
DerivedTwo();
virtual void doSomething();
};
然后,您可以使用dynamic_cast
来确定运行时的类型,因为您似乎在SomeClass
中的某个位置具有类型条件表达式。这些方法不相同,根本不同。另外,DerivedOne::doSomething
会隐藏Base::doSomething
。
<强>更新强>
正如其他人已经说过的那样,如果你的程序依赖于类型条件表达式,那通常是一种难闻的气味。由于您的示例没有足够的上下文来提供适当的解决方案,因此我们很难在这方面为您提供帮助。如果您有兴趣删除类型条件,那么这个问题的许多潜在解决方案之一将是:
class Base {
public:
Base();
virtual ~Base();
virtual void doSomething();
};
class DerivedOne : public Base {
public:
DerivedOne();
// ...
virtual void doSomething(); // << no parameters required.
// they have moved to member data:
private:
int a;
b another;
};
class DerivedTwo : public Base {
public:
DerivedTwo();
virtual void doSomething();
};
然后你可以从你的程序中删除类型条件表达式。如果你想在这方面提供帮助,请随时在这里提问,或者如果你觉得更合适,可以打开一个新问题。
答案 3 :(得分:0)
我们能解决这个问题吗? :
class Base {
public:
void virtual doSomething();
void virtual doSomething(int a,struct b);
}
class DerivedOne : Base {
public:
void doSomething(int a,struct b);
}
class DerivedTwo : Base {
public:
void doSomething();
}
答案 4 :(得分:0)
在你的例子中你可以使用RTTI而不是if / else所以你实例化DerivedOne和DerivedTwo然后你将Base指针转换为两者(DerivedOne和DerivedTwo),所以结果是其中一个是NULL。然后你检查所需的Derived对象是不是NULL,如果是,你调用函数:
DerivedOne *pDrvOne=dynamic_cast<DerivedOne*>(pBase);
DerivedTwo *pDrvTwo=dynamic_cast<DerivedTwo*>(pBase);
then: if(pDrvOne)pDrvOne->deSo,ething(a,b); if(pDrvTwo) pDrvTwo->doSomething();
* 记住使用RTTI会破坏多态性的原则。 在您的示例中,您没有在DerivedOne子类中重载doSomething():“重载函数是使用相同的签名(函数名称和相同数量和类型的参数)”。但你只是在DerivedTwo中重载它。因此考虑这个例子:
Base *pBs;
pBs=new DerivedOne; pBs->doSomething(a,b); the result a call to base doSomthing!!!
*解决方案是尝试了解您的课程要解决的问题。
答案 5 :(得分:0)
与Taras的例子类似..只需在Taras的例子中为Base和DerivedTwo的原型添加'默认值'。这样,使用Base类或DerivedTwo类的其余代码将不必更改。