按成员值强制转换

Cast by member value

本文关键字:转换 成员      更新时间:2023-10-16

根据对象实例的成员值强制转换对象实例时遇到问题。测试用例:

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

想象一下,我们在三元运算符中有数百个子类和数百个case,它们都是在宏中编写的。我应该如何解决这个问题?如果我在三元运算符中放入更多的事例,我会得到错误"不同指针类型之间的条件表达式"。是的,测试变量需要是一个基类指针。这只是一个简短的例子。

首先,您的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. 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);

为此,请使用开关:

Base * test = //something returning a Base *
switch(test)
{
   case 0 :
      static_cast<Derived0*>(test)/*[...]*/;
      break;
   case 1 :
      static_cast<Derived1*>(test)/*[...]*/;
      break;
//...
}

如果只有一个类返回相同的type(),那么,您可以使用static_cast,因为您确信这一点。