1

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

编辑 :

我得到的错误是,

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

谢谢

4

3 回答 3

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);
于 2013-10-31T10:44:17.077 回答
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();

}
于 2013-10-31T10:45:16.740 回答
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 中扩展现有的类,而无需通知编写基类的人,这就是继承的用途。尽管在可以标记 class 的语言中final,如果您不想在这种情况下允许它,这可能是一个好主意(并且 IIRC C++11 提供了一种方法来做到这一点,我只是不知道如何拼写它)。

于 2013-10-31T10:57:57.087 回答