C++ C++;基类列表以及如何确定类类型
我有一个基类C++ C++;基类列表以及如何确定类类型,c++,class,vector,C++,Class,Vector,我有一个基类line,它有一个子类arc(请注意,其他类将继承自line)。。。我需要存储行对象的列表或向量,这些对象可能是行或弧弧有一个行没有的附加属性。因此,当我处理行对象的列表或向量时,如何确定该对象是行还是弧 我已经准备了一个小的示例程序,并在注释中加入了伪代码,这是我试图实现的一个示例。这可能吗 #include <iostream> #include <vector> #include <iterator> using namespace std
line
,它有一个子类arc
(请注意,其他类将继承自line
)。。。我需要存储行
对象的列表或向量
,这些对象可能是行
或弧
<代码>弧有一个行
没有的附加属性。因此,当我处理行
对象的列表或向量
时,如何确定该对象是行
还是弧
我已经准备了一个小的示例程序,并在注释中加入了伪代码,这是我试图实现的一个示例。这可能吗
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
struct point
{
double x;
double y;
};
class line
{
public:
point start;
point end;
};
class arc: public line
{
public:
point center;
};
int main( int argc, char* argv[] )
{
vector<line*> a;
a.push_back( new line );
a.push_back( new arc );
for( vector<line*>::iterator i = a.begin(); i < a.end(); i++ )
{
(*i)->start.x = 10;
(*i)->start.y = 11;
(*i)->end.x = 101;
(*i)->end.y = 102;
//if( type of (*i) is arc )
//{
// (i)->center.x = 111;
// (i)->center.y = 112;
// }
}
return 0;
}
#包括
#包括
#包括
使用名称空间std;
结构点
{
双x;
双y;
};
班级线
{
公众:
起点;
点端;
};
等级:公共线路
{
公众:
点中心;
};
int main(int argc,char*argv[])
{
载体a;
a、 推回(新线);
a、 向后推(新弧);
对于(向量::迭代器i=a.begin();istart.x=10;
(*i)->start.y=11;
(*i)->end.x=101;
(*i)->end.y=102;
//if(类型(*i)为圆弧)
//{
//(i)->center.x=111;
//(i)->中心y=112;
// }
}
返回0;
}
为什么需要确定?如果您确实需要,您可以通过RTTI使用typeid字段。但通常情况下,如果您使用虚拟方法,如果您的程序设计良好,则不需要知道类是什么。在基类引用或指针上调用虚函数将根据其指向的对象调用相应实例的方法。
这就是通过类层次结构实现多态性的全部意义
但是,如果您确实需要知道实例属于哪个类,请再次使用typeid
此外,您不能通过基类指针访问派生类成员数据。您只能通过基类接口进行对话。这就是抽象的全部要点。
一种丑陋的方法是创建一个fat接口,该接口将访问器/变异器作为虚拟成员函数提供给基类接口中的这些数据成员。在循环中,尝试以下操作:
arc *ar = dynamic_cast<arc *>(*i);
if ( NULL != ar ) {
// it's an arc!
}else {
// it's just a line
}
arc*ar=dynamic_cast(*i);
如果(NULL!=ar){
//这是一个弧线!
}否则{
//这只是一句台词
}
Sid也是正确的…请改用虚拟函数。对于这种简单的情况,使用dynamic_cast通常被认为是拙劣的风格
class curve
{
public:
typedef void * type;
public:
virtual type rtti() const = 0;
};
#define
DEFINE_RTTI \
public: \
virtual type rtti() const { return desc(); } \
public: \
inline static type desc() { return &desc; } \
class line : public curve
{
DEFINE_RTTI;
};
class arc : public curve
{
DEFINE_RTTI;
};
///////////////////////////////////////////////////////////////////////////////
// Main program
int main()
{
arc arc_;
line line_;
curve *curve_ = new arc();
_ASSERT(arc_.rtti() == arc::desc());
_ASSERT(arc_.rtti() != line::desc());
_ASSERT(line_.rtti() != arc::desc());
_ASSERT(line_.rtti() == line::desc());
return 0;
}
这个rtti在一个模块(exe或dll)内工作,如果您想在多个模块中使用它,您必须构建类字典,除了
main
函数之外,我的示例中绝对没有函数,更不用说虚拟函数了。我曾尝试使用typeid()
函数来确定类类型,但是,我所有的努力都导致了编译器错误,或者它返回了指针类型,而不是实际的类。最后,这并不能解决访问基类中未定义的对象成员的问题……您确定在编译器中启用了rtti吗。我认为他们中的很多人都必须有一个选择——启用rtti或者类似的东西。请参阅我的编辑。是的,rtii在我目前使用的g++中默认启用。您向我介绍了一些我不熟悉的新术语(访问器、变异器)。你有这样做的例子吗?arc
将有各种各样的函数,例如getRadius()
,这些函数不适用于line
,因此在这个项目上使用虚拟函数对我来说毫无意义。我看到过与您在这里发布的示例类似的示例,但我在尝试时遇到了这个编译器错误<代码>无法动态地将“i.”转换为“:“普通”迭代器::运算符*[带迭代器=行**,_容器=标准::向量,u gnu cxx::“普通”迭代器::引用=行*&()”(属于“类行*”)类型为“类弧*”(源类型不是多态的)啊,是的,缺少的vtable。嗯……您可以通过在类行中使(空)析构函数为虚拟来添加一个析构函数。这不是最好的方法,但它会起作用。那么,回到Sid的观点,为什么你需要把它们放在一个集装箱等待线*?如果这里没有任何虚拟函数,这似乎不太合适。我通过在基类中至少添加一个虚拟函数来实现您的示例。你说这是一种糟糕的做法,但除非我想用虚拟成员扩充我的基类,否则它真的不需要,除此之外,我看不到任何其他选项……因为我需要这些类型对象的列表,每个项目可以是行
或弧
或我尚未添加的其他类型的行
。此外,它们将被写入/读取到纯文本文件中,因此我需要在遍历它们时确定它们的实际类型,以便在文件中指示。