我正在尝试从基类的对象中访问派生类的方法。我有一个基类CBase
,它是抽象类,
class CBase{
protected:
char path[255];
public:
virtual void StartBackup()=0;
void setpath(char * path)
{
strcpy(this->path,path);
}
virtual void afunc()
{
printf("Base\n");
}
};
现在两个类Ctype1和Ctype2是来自CBase的派生类
class CType1:public CBase{
public:
void StartBackup()
{
printf("Type1:%s",path);
}
void afunc()
{
printf("CType1:afunc\n");
}
void myfunc()
{
printf("myfunc\n");
}
};
class CType2:public CBase{
public:
void StartBackup()
{
printf("Type2:%s",path);
}
void afunc()
{
printf("type2:afunc\n");
}
void typefunc()
{
printf("typefunc\n");
}
};
我有一个CManager类,它有一个CBase类的对象作为其成员,
class CManager{
private:
CBase * obj;
public:
CManager(){
obj = NULL;
}
~CManager(){
if(obj)
delete obj;
obj = NULL;
}
void inittype(int type)
{
if(type == 1)
{
obj = new CType1();
obj->myfunc();
}
else
{
obj = new CType2();
obj->typefunc();
}
}
};
在void inittype(int type)
函数中,我将输入作为类型并相应地初始化CBase对象。
我面临的问题是,在我尝试访问myfunc
或typefunc
后创建对象后,我得到编译错误。我如何访问这些函数(我不想在基类中创建这些函数)?
编辑:
我得到的错误,
谢谢
答案 0 :(得分:3)
如果您只需要在创建时访问类非派生函数,那么这将起作用
void inittype(int type)
{
if(type == 1)
{
CType1* temp = new CType1();
temp->myfunc();
obj = temp;
}
else
{
CType2* temp = new CType2();
temp ->typefunc();
obj = temp;
}
}
如果您需要在其他时间访问这些成员函数,则需要使用强制转换 - 例如
CType2* child = dynamic_cast<CType2*>(obj);
答案 1 :(得分:3)
在基类中创建一个inittype虚函数(什么都不做),然后根据需要在派生类中重写它。
void CType1::inittype() {
myfunc();
}
void CType2::inittype() {
typefunc();
}
void CManager::inittype(int type)
{
if(type == 1)
{
obj = new CType1();
}
else
{
obj = new CType2();
}
obj->inittype();
}
答案 2 :(得分:1)
我不清楚你的意思是“我不想在基类中创建这些函数”。
您似乎了解纯虚函数。如果您在CBase中将问题函数声明为纯函数,则应该能够通过CBase *
指针调用它们。
面向对象语言的一个可能的混淆是“这是什么类型”根据上下文有两个答案。创建新对象时,类型是确切类型。当您通过引用或指针访问现有对象时,类型是一组可能的类型 - 基类和可能存在的所有子类。更准确地说,指针/引用的类型定义了可用于访问对象的接口。必须知道该接口而不引用派生类(在编译基类时可能不存在),因此必须在基类中声明它 - 虚拟方法。
如果要调用仅在派生类中已知的内容,则有两个选项。一个是不要忘记派生类。例如......
CType1 *temp = new CType1();
obj = temp;
temp->myfunc();
另一个是确定您在运行时使用的派生类,并使用强制转换来转换指针。 (相对)安全的方法是使用dynamic_cast
。
CType1 *temp = dynamic_cast<CType1> (obj);
if (temp) { temp->myfunc (); }
我没有介绍如何在运行时识别类型。 C ++中内置了“运行时类型识别”(RTTI)来实现这一点,但我很少使用它。在dynamic_cast
是正确的事情的极少数情况下,我总是因为其他原因而知道该类型 - 要么对象是在一组封闭的类中,无论如何都可以通过某些界面中的功能来识别,或者那里只有一种可能性出现在需要dynamic_cast
的代码中。
这里的关键词是“封闭的类集” - 如果其他人从您的类继承,当您不知道并且因此无法识别的类型的对象被您的代码访问时,您可能会遇到意外问题。对于OOP来说,这不是一个真正的问题,它是一个设计的功能 - 你应该能够在不通知编写基类的人的情况下扩展OOP中的现有类,这就是继承的目的。虽然在你可以标记类final
的语言中,如果你不想在这种情况下允许它,这可能是一个好主意(并且IIRC C ++ 11提供了一种方法来做到这一点,我只是'不'我知道如何拼写它。)