无法在c ++中访问派生类的功能

时间:2013-10-31 10:38:02

标签: c++ oop inheritance

我正在尝试从基类的对象中访问派生类的方法。我有一个基类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对象。

我面临的问题是,在我尝试访问myfunctypefunc后创建对象后,我得到编译错误。我如何访问这些函数(我不想在基类中创建这些函数)?

编辑:

我得到的错误

  1. 'myfunc':不是'CBase'的成员
  2. 'typefunc':不是'CBase'的成员
  3. 谢谢

3 个答案:

答案 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提供了一种方法来做到这一点,我只是'不'我知道如何拼写它。)