多态成员变量

时间:2012-11-20 13:46:20

标签: c++ segmentation-fault polymorphism

我昨天就polymorphic object members的问题得到了一个优雅的答案。

但是现在我面临的问题是变量并没有像我预期的那样表现。正在使用以下代码:

#include <iostream>
#include <math.h>

using std::cin;
using std::cout;
using std::endl;


class Com
{
    public:
        virtual void setReady()
        {
            cout << "Com" << endl;
        }
};

class DerivedCom : public Com
{
    public:
        void setReady()
        {
            cout << "DCom" << endl;
        }

        void somethingElse()
        {
            cout << "else" << endl;
        }

};

class BaseClass
{
    public:
        Com* com;

    public:
        BaseClass(Com* c = new Com) : com(c)
        {
        }

        virtual void setReady()
        {
            com->setReady();
        }
};

class DerivedClass : public BaseClass
{
    // the call to somethingElse() won't compile if I leave out this declaration
    protected:
        DerivedCom* com;

    public:
        DerivedClass() : BaseClass(new DerivedCom) 
        {
        }

        void setReady()
        {
            // This line causes a segfault if I put in the declaration earlier
            this->com->setReady();

            // This line won't compile if I leave out the declaration earlier
            this->com->somethingElse();
        }
};

int main()
{
    DerivedClass* inst = new DerivedClass();

    inst->setReady();
    return 0;
}

问题是,DerivedClass::com实际上是DerivedCom类型但我无法访问任何DerivedCom特定方法,因为编译器无法找到它们。如果我进行额外的重新声明DerivedCom* com,编译器会找到方法,但我会遇到分段错误。

2 个答案:

答案 0 :(得分:3)

删除该额外声明。

如果您确定Com*DerivedCom*,那么您可以static_cast

static_cast<DerivedCom*>(this->com)->somethingElse();

然而,这可能会让你崩溃。所以如果你不确定那么你可以dynamic_cast

DerivedCom* dcom = dynamic_cast<DerivedCom*>(this->com);
if (dcom)
    dcom->somethingElse();
如果对象不是您要求的类型,

dynamic_cast将返回NULL。

答案 1 :(得分:0)

分段错误的原因是你没有用另一种类型再次声明变量,你实际上在派生类中定义一个新指针,一个从未初始化。因此,this->com->...将访问派生类com并崩溃,因为它是未初始化的指针

您尝试做的是更改成员指针的类型。你可以通过将成员指针的类型作为模板变量来实现,如下所示

template <class ComType>
class BaseClassTemplate
{
    ComType* com;
    ...;
};

typedef BaseClassTemplate<Com> BaseClass;

class DerivedClass : public BaseClassTemplate<DerivedCom>
{
    ...;
};

然而,这使得基类成为模板,因此要根据需要获取它,您需要进行BaseClass<Com>的实例化以获取您的基类版本。您可以将其设为派生类,也可以只显示我所显示的typedef。