0

I've got a problem with casting an object instance by the value of its member. The test case:

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();
}

Imagine, that we have hundreds of child classes and hundreds of cases in the ternary operator all written in a macro. How should I solve this problem? If i put more cases in the ternary operator i got error 'conditional expression between distinct pointer types'. And yeah, the test variable needs to be a base class pointer. It's just a short example.

4

3 回答 3

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(); 
}
于 2013-08-12T12:24:24.457 回答
1
  1. NULL->derivedspecific()不会编译
  2. ((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());

你可以在这里尝试完整的代码。

至于您的评论:您可以用自由功能替换宏(无论如何都是可取的)

void derived1specific(base* b){
    if(derived1* d1 = dynamic_cast<derived1*>(b))
        d1->derived1specific();
}

这正是您的代码想要做的:当且仅当它合适时才执行派生的特定函数;您只需将其称为:

derived1specific(test);
于 2013-08-12T12:22:49.410 回答
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,因为你确定。

于 2013-08-12T12:29:24.607 回答