3

我有两个类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's 对象?我能想到的一种解决方案是dynamic_cast检查它NULL。这是最好的解决方案还是我可以有更好的解决方案?

4

4 回答 4

5

这意味着您的test功能在撒谎。意思是它会接受一个指向任何A对象的指针,甚至是派生自. 你最好采取以下措施:ABB*

void test(B* ptr)
{
   ptr->get_data();
]
于 2013-04-20T12:34:32.730 回答
4

如果你可以改变Aand的接口B(包括添加虚函数),如果你可以重新洗牌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才会调用该方法。

于 2013-04-20T13:05:10.877 回答
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();
    });
}
于 2013-04-20T12:52:59.893 回答
-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();
}
于 2013-04-20T13:02:34.977 回答