C++ C++;多态性从基类访问派生类字段
我有以下计划:C++ C++;多态性从基类访问派生类字段,c++,polymorphism,C++,Polymorphism,我有以下计划: #include <iostream> class Base {}; class Deriv : public Base { public: int data; Deriv(int data): data(data) {} }; int main() { Base *t = new Deriv(2); std::cout << t->data << std::endl; }
#include <iostream>
class Base {};
class Deriv : public Base
{
public:
int data;
Deriv(int data): data(data) {}
};
int main()
{
Base *t = new Deriv(2);
std::cout << t->data << std::endl;
}
如何访问数据字段(请注意,我不想使用Deriv*t=new Deriv(2))?您已将指针声明为
Base
类型,并且编译器是正确的,该类中没有成员数据。为了以这种方式访问成员,您需要将指针转换回Deriv*
。为什么要将类型指针设置为基类?这通常仅在具有多态类层次结构时有用
你可以考虑使用一个虚拟函数来返回这个成员的值,但是不知道你的类和代码试图实现什么,很难推荐一种或另一种方式。基于您的小代码示例,只需使用
Deriv *t = new Deriv(2);
相反,似乎是一个更好的选择您已将指针声明为Base
类型,并且编译器是正确的,该类中没有成员数据
。为了以这种方式访问成员,您需要将指针转换回Deriv*
。为什么要将类型指针设置为基类?这通常仅在具有多态类层次结构时有用
你可以考虑使用一个虚拟函数来返回这个成员的值,但是不知道你的类和代码试图实现什么,很难推荐一种或另一种方式。基于您的小代码示例,只需使用
Deriv *t = new Deriv(2);
相反,似乎是一个更好的选择将其置于基类:
virtual int get_data() const=0;
然后派生类将需要实现它-所有派生类的所有数据都将通过接口:
class Base
{
virtual int get_data() const = 0;
};
class Deriv: public Base
{
public:
int data;
Deriv(int data): data(data) {}
virtual int get_data() const
{ return data; }
};
将其放入基类:
virtual int get_data() const=0;
然后派生类将需要实现它-所有派生类的所有数据都将通过接口:
class Base
{
virtual int get_data() const = 0;
};
class Deriv: public Base
{
public:
int data;
Deriv(int data): data(data) {}
virtual int get_data() const
{ return data; }
};
对象t
具有指向-Base
的类型指针,并且Base
未定义data
成员,这就是代码无法编译的原因。如果您确实知道t
指向类型为Deriv
的实际对象(就像您发布的代码一样),您可以强制转换它,以便能够调用Deriv
成员:
Deriv* d = static_cast<Deriv*>(t);
std::cout << d->data << std::endl;
在任何情况下,根据您发布的代码,如果您只是使用它访问仅由Deriv
定义的数据成员,那么通过将t
声明为Base*
,您实际上并没有获得任何收益,而Base
对象t
具有指向-Base
的类型指针,并且Base
没有定义数据
成员,这就是代码无法编译的原因。如果您确实知道t
指向类型为Deriv
的实际对象(就像您发布的代码一样),您可以强制转换它,以便能够调用Deriv
成员:
Deriv* d = static_cast<Deriv*>(t);
std::cout << d->data << std::endl;
在任何情况下,根据您发布的代码,如果您只是使用t
作为Base*
来访问仅由Deriv
定义的数据成员,则必须首先将其强制转换为指定的类型。@AtoMerZ,这是唯一的方法吗?取决于您的要求。你也可以照@tp1说的做。Base无法了解数据。您必须以这样或那样的方式告诉它。您必须首先将它转换为指定的类型。@AtoMerZ,这是唯一的方法吗?取决于您的要求。你也可以照@tp1说的做。Base无法了解数据。你必须以这样或那样的方式告诉它。标准的解决方案+1.你应该提到这个也在Base中。也许Base不应该有这个功能。这怎么可能是标准的?@AtoMerZ这是标准的,因为它避免了类切换并引入了一个合适的接口。@tp1,你能解释一下吗?基本接口只需要设计成所有派生类都可以通过它传递数据。如果Derived2允许2个整数,那么您已经需要基类中的动态数组。标准解决方案+1.你应该提到这个也在Base中。也许Base不应该有这个功能。这怎么可能是标准的?@AtoMerZ这是标准的,因为它避免了类切换并引入了一个合适的接口。@tp1,你能解释一下吗?基本接口只需要设计成所有派生类都可以通过它传递数据。如果Derived2允许2个整数,那么基类中就已经需要动态数组了。我用一个小例子来说明我的问题。我将在需要的地方使用((Deriv*)t)->数据。@gg.kaspersky哦,我明白了,这在代码中并不明显。也许从长远来看,虚函数方法是一种可行的方法。该数据字段仅适用于Deriv类。我不想做一个虚拟的吸气剂,并强制所有继承基类的人实现它.@ G.Kaspaskok:只要你的代码工作得怎么样,那是最重要的东西,当你在C++中铸造时,你应该更喜欢使用C++风格的一个铸件,而不是普通的C风格的铸件:<代码> StasyType(t)< /C>我有一个多态类层次结构。我用一个小例子来说明我的问题。我将在需要的地方使用((Deriv*)t)->数据。@gg.kaspersky哦,我明白了,这在代码中并不明显。也许从长远来看,虚函数方法是一种可行的方法。该数据字段仅适用于Deriv类。我不想做一个虚拟的吸气剂,并强制所有继承基类的人实现它.@ G.Kaspaskok:只要你的代码工作得怎么样,那是最重要的东西,当你在C++中铸造时,你应该更喜欢使用C++风格的一个铸件,而不是普通的C风格的铸件:<代码> StasyType(t)
请注意,动态\u cast具有合理的运行时开销,有时需要设置编译时标志才能在某些编译器中正常工作