C++ 多态成员变量
我昨天得到了一个关于我的问题的优雅的答案 但现在我面临的问题是,变量的行为并不是我所期望的那样。正在使用以下代码:C++ 多态成员变量,c++,segmentation-fault,polymorphism,C++,Segmentation Fault,Polymorphism,我昨天得到了一个关于我的问题的优雅的答案 但现在我面临的问题是,变量的行为并不是我所期望的那样。正在使用以下代码: #include <iostream> #include <math.h> using std::cin; using std::cout; using std::endl; class Com { public: virtual void setReady() { cout <&l
#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;
}
#包括
#包括
使用std::cin;
使用std::cout;
使用std::endl;
类Com
{
公众:
虚拟void setReady()
{
cout setReady();
返回0;
}
问题是,
DerivedCom::com
实际上是DerivedCom
类型,但我无法访问任何特定于DerivedCom
的方法,因为编译器无法找到它们。如果我加入额外的重新声明DerivedCom*com
,编译器将找到这些方法,但会出现分段错误。删除该extr声明
如果您确定Com*
是DerivedCom*
的,那么您可以static\u cast
static_cast<DerivedCom*>(this->com)->somethingElse();
如果对象不是您要求的类型,
dynamic\u cast
将返回NULL。删除该额外声明
如果您确定Com*
是DerivedCom*
的,那么您可以static\u cast
static_cast<DerivedCom*>(this->com)->somethingElse();
dynamic\u cast
如果对象不是您要求的类型,将返回NULL。分段错误的原因是您没有使用不同的类型再次声明变量,您实际上是在派生类中定义了一个新指针,一个从未初始化过的指针。因此s->com->…
将访问派生类com
并崩溃,因为它是一个未初始化的指针
但是,您要做的是更改成员指针的类型。。您可以通过将成员指针的类型设置为模板变量来执行此操作,如下所示
template <class ComType>
class BaseClassTemplate
{
ComType* com;
...;
};
typedef BaseClassTemplate<Com> BaseClass;
class DerivedClass : public BaseClassTemplate<DerivedCom>
{
...;
};
模板
类BaseClassTemplate
{
ComType*com;
...;
};
typedef基类模板基类;
类DerivedClass:公共BaseClassTemplate
{
...;
};
然而,这使得基类成为一个模板,因此,要想获得所需的基类,您需要实例化
BaseClass
以获得您的基类版本。您可以将其设置为派生类,也可以将其设置为typedef,如我所示。分段错误的原因是您没有再次声明变量使用不同的类型,您实际上是在派生类中定义了一个新指针,一个从未初始化过的指针。因此,this->com->……
将访问派生类com
,并且由于它是一个未初始化的指针而崩溃
但是,您要做的是更改成员指针的类型。。您可以通过将成员指针的类型设置为模板变量来执行此操作,如下所示
template <class ComType>
class BaseClassTemplate
{
ComType* com;
...;
};
typedef BaseClassTemplate<Com> BaseClass;
class DerivedClass : public BaseClassTemplate<DerivedCom>
{
...;
};
模板
类BaseClassTemplate
{
ComType*com;
...;
};
typedef基类模板基类;
类DerivedClass:公共BaseClassTemplate
{
...;
};
然而,这使得基类成为一个模板,所以要想得到你想要的,你需要实例化
BaseClass
来得到你的基类版本。你可以把它变成一个派生类,或者像我所展示的那样仅仅是一个typedef。它工作得很好,很有趣!有没有办法只进行一次静态转换,然后简单地使用这个->com
在类的其余部分中?不,您正在创建的静态强制转换指针是本地范围的。您必须保留该重新声明才能在类中的所有位置使用此->com确保只声明一个成员变量(但称为与com
不同的名称)然后在构造函数中初始化它。但是我想我宁愿每次都静态地抛出它,复制信息是不好的。比如…声明DerivedCom*com
并在构造函数中执行this->com=static\u cast(BaseClass::com);
。或者这只是一个丑陋的黑客行为吗?如果你拥有代码,你也可以添加一个存根(空主体)对基类的somethingElse()
实现,或声明somethingElse()
在基类中是纯虚拟的。这很有效,很有趣!有没有办法进行一次静态强制转换,然后在类的其余部分简单地使用this->com
?没有,您正在进行的静态强制转换指针是本地范围的。您必须保留该重新声明才能在类中的所有位置使用此->com确保只声明一个member变量(但调用了与com
不同的东西)并在构造函数中对其进行初始化。但我想我宁愿每次都静态地调用它,复制信息是不好的。例如…声明DerivedCom*com
并执行this->com=static\u cast(BaseClass::com)
在构造函数中。或者这只是一个丑陋的黑客行为?如果您拥有代码,您还可以将somethingElse()
的存根(空体)实现添加到基类中,或者声明somethingElse()
基类中的纯虚拟。在这段代码中,我看不到虚拟dtor,如果在基类上调用delete时需要级联dtor调用,这是必不可少的。这只是一个概念证明。我想我不需要dtors.well,[多态性]标记,至少不需要virtual~Com{}
看起来很奇怪。@NilsWerner:这已经在原始问题的评论中提到了(特别是问题的第三条评论)。在这段代码中,我没有看到虚拟dtor,如果在基类上调用delete时需要级联dtor调用,这是必不可少的。这只是一个概念证明。我想我不需要dtor。嗯,[多态性]标记,至少不需要virtual~Com{}
看起来很奇怪。@NilsWerner:这已经在原始问题的评论中提到了(特别是问题的第三条评论)。