我有两个课程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
。它是最好的解决方案还是我能有更好的解决方案?
答案 0 :(得分:5)
这意味着您的test
功能正在撒谎。它表示它将接受指向任何A
对象的指针,甚至是从A
派生的类型,但该函数实际上不适用于B
以外的任何其他内容。你最好选择B*
:
void test(B* ptr)
{
ptr->get_data();
]
答案 1 :(得分:4)
如果您可以更改A
和B
的界面(包括添加虚拟功能),并且您可以重新随机播放test
功能中的代码,则可以使用“访问者”图案”。以下是使用更好的名为Base
和Derived
类的示例:
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();
}