多态成员变量



我昨天得到了一个关于多态对象成员的问题的优雅答案。

但是现在我面临的问题是,变量并没有真正按照我预期的方式运行。正在使用以下代码:

#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,编译器会找到方法,但我得到分段错误。

删除该额外的声明。

如果您确定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。

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

不过,您要做的是更改成员指针的类型。您可以通过将成员指针的类型作为模板变量来执行此操作,如下所示

template <class ComType>
class BaseClassTemplate
{
    ComType* com;
    ...;
};
typedef BaseClassTemplate<Com> BaseClass;
class DerivedClass : public BaseClassTemplate<DerivedCom>
{
    ...;
};

但是,这使基类成为模板,因此要根据需要获取它,您需要实例化BaseClass<Com>以获取基类的版本。你可以让它成为一个派生类,也可以只是一个typedef,如我所展示的。

相关内容

  • 没有找到相关文章

最新更新