我遇到了通过其成员的值转换对象实例的问题。 测试案例:
class base {
public:
virtual int type() const = 0;
};
class derived : public base {
public:
virtual int type() const { return 1; }
virtual void derivedspecific() {}
};
int main() {
base* test = new derived;
(test->type()==1?((derived*)test):NULL)->derivedspecific();
}
想象一下,我们在三元运算符中有数百个子类和数百个案例都是用宏编写的。我该如何解决这个问题?如果我在三元运算符中放入更多的情况,我会得到错误'不同指针类型之间的条件表达式'。是的,测试变量需要是基类指针。这只是一个简短的例子。
答案 0 :(得分:2)
首先,你的derivedspecific
不需要是虚拟的,因为看起来你没有通过指向基类的指针来调用它。我假设派生类中的名称总是不同的。
否则,如果derivedspecific
始终是相同的名称和签名,则实际上并不需要type()
:
class base
{
public:
virtual int doWork() const = 0;
};
class derived : public base
{
public:
virtual void doWork() { /* do your work here*/ }
};
int main()
{
base* test = new derived;
test->doWork();
}
答案 1 :(得分:1)
NULL->derivedspecific()
无法编译((derived*)NULL)->derivedspecific()
是未定义的行为(大多数平台上的分段错误)有一种机制专门用于支持这种行为,即dynamic_cast
如下:
#include <typeinfo>
class base
{
public:
virtual ~base(){};
};
class derived1 : public base
{
public:
void derived1specific() const {}
};
class derived2 : public base
{
public:
void derived2specific() const {}
};
int main()
{
// use pointers
base* test = new derived1;
derived2* d2 = dynamic_cast<derived2*>(test);
if(d2)
d2->derived2specific();
derived1* d1 = dynamic_cast<derived1*>(test);
if(d1)
d1->derived1specific();
// or simply
if(derived1* d1 = dynamic_cast<derived1*>(test) )
d1->derived1specific();
else if(derived2* d2 = dynamic_cast<derived2*>(test))
d2->derived2specific();
// use references
const base& testr = derived1();
try{
const derived1& d1 = dynamic_cast<const derived1&>(testr);
d1.derived1specific();
}
catch(std::bad_cast&){}
try{
const derived2& d2 = dynamic_cast<const derived2&>(testr);
d2.derived2specific();
}
catch(std::bad_cast&){}
}
你想做什么,我不推荐你,是这样的:
auto doNothing = [](){return;};
(test->type()==1?(((derived1*)test)->derived1specific()):doNothing());
您可以尝试完整代码here。
至于你的评论:你可以用自由函数代替宏(无论如何这是可行的)
void derived1specific(base* b){
if(derived1* d1 = dynamic_cast<derived1*>(b))
d1->derived1specific();
}
完全符合您的代码要执行的操作:当且仅当它适当时才执行派生的特定函数;你只需称它为:
derived1specific(test);
答案 2 :(得分:0)
为此,请使用开关:
Base * test = //something returning a Base *
switch(test)
{
case 0 :
static_cast<Derived0*>(test)/*[...]*/;
break;
case 1 :
static_cast<Derived1*>(test)/*[...]*/;
break;
//...
}
如果只有一个类返回相同的类型(),那么,你可以使用static_cast,因为你确定。