按会员价值转换

时间:2013-08-12 12:18:00

标签: c++ c++11 g++

我遇到了通过其成员的值转换对象实例的问题。 测试案例:

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

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

3 个答案:

答案 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)

  1. NULL->derivedspecific()无法编译
  2. ((derived*)NULL)->derivedspecific()是未定义的行为(大多数平台上的分段错误)
  3. 有一种机制专门用于支持这种行为,即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,因为你确定。