创建函数获取基类指针但调用派生类函数

时间:2013-04-20 12:32:14

标签: c++ inheritance

我有两个课程A(基础)和B(源自A):

class A { };

class B : public A
{
    int data;
public:
    int get_data() { return data; }
};

现在我有一个函数测试,它接受基类指针并调用派生类函数:

void test(A * ptr)
{
    ptr->get_data();
}

但问题是ptr可能指向A的对象或B的对象。如果它指向B的对象,那么确定,但如果是A的对象,那么这是一个问题。

此外,我不想让get_data()虚拟,因为data不是A对象的属性。

如何检查ptr是否指向B的对象?我能想到的一个解决方案是dynamic_cast并检查NULL。它是最好的解决方案还是我能有更好的解决方案?

4 个答案:

答案 0 :(得分:5)

这意味着您的test功能正在撒谎。它表示它将接受指向任何A对象的指针,甚至是从A派生的类型,但该函数实际上不适用于B以外的任何其他内容。你最好选择B*

void test(B* ptr)
{
   ptr->get_data();
]

答案 1 :(得分:4)

如果您可以更改AB的界面(包括添加虚拟功能),并且您可以重新随机播放test功能中的代码,则可以使用“访问者”图案”。以下是使用更好的名为BaseDerived类的示例:

class Visitor
{
public:
    void Visit(Base * B)
    {
    }

    void Visit(Derived * D)
    {
        int data = D->get_data();
    }
};

class Base
{
public:
    virtual void Accept(Visitor * V )
    {
        V->Visit(this);
    }
};

class Derived: public Base
{
public:
    int get_data()
    {
        return data;
    }

    virtual void Accept(Visitor * V )
    {
        V->Visit(this);
    }
private:
    int data;
};

通过这种方式,您可以迭代Base*的向量,调用每个元素的Accept,并且只知道Derived元素将调用get_data方法。< / p>

答案 2 :(得分:0)

继承模拟is-a关系。显然,在你的代码中,B不是A,继承是错误的模型。你在评论中提到你有一个向量传递给一个封闭的,更大的函数。我建议以下其中一个更合适:

  1. std::vector<boost::any>
  2. std::vector<boost::variant<A,B>>

修改 以下是使用boost变体的示例:

class A
{
public:
    void DoIt()
    {
        std::cout << "did it!" << "\n";
    }
};

class B
{
public:
    void GetIt()
    {
        std::cout << "got it!" << "\n";
    }
};

typedef boost::variant<A,B> ab_t;
typedef std::vector<ab_t> list_ab;

void test(list_ab& list)
{
    std::for_each(std::begin(list), std::end(list), [](ab_t& item)
    {
        if(A* a = boost::get<A>(&item))
            a->DoIt();
        if(B* b = boost::get<B>(&item))
            b->GetIt();
    });
}

答案 3 :(得分:-4)

你说实际上你有一个元素A或B的向量,那么你的测试函数看起来真的如下:

void test( A ** ptr )

然后你可以使用重载C ++功能来创建一个实用程序函数,将调用正确的函数:

void test( A ** ptr ) {
    A * elem;
    int i=0;
    elem = ptr[i++];
    while(elem) {
        testElement(elem);
        elem = ptr[i++];
    }
}

void testElement( A * ptr ) { }
void testElement( B * ptr ) {
    ptr->get_data();
}