C++ 虚拟方法 return 不同的派生类型
C++ Virtual Method return different derived types
参考这个问题:C++ virtual function return type
让我们考虑以下一组对象。
class ReturnTypeBase
{
};
class ReturnTypeDerived1 : public ReturnTypeBase
{
public:
int x;
};
class ReturnTypeDerived2 : public ReturnTypeBase
{
public:
float y;
};
class Base
{
public:
virtual ReturnTypeBase* Get() = 0;
};
class Derived1: public Base
{
public:
virtual ReturnTypeDerived1* Get()
{
return new ReturnTypeDerived1();
}
};
class Derived2: public Base
{
public:
virtual ReturnTypeDerived2* Get()
{
return new ReturnTypeDerived2();
}
};
这些对象可以按以下方式使用吗?
Base* objects[2];
objects[0] = new Derived1();
objects[1] = new Derived2();
ReturnTypeDerived1* one = objects[0]->Get();
ReturnTypeDerived2* two = objects[1]->Get();
我假设因为 return 类型是协变的(?),上面的对象集是合法的 C++。是否会调用适当的 Get() 方法?指针 one/two 是否可以在不强制转换的情况下分配给 Get() 方法的 return 值?
代码将不会像编写的那样编译。因为 objects[0]
具有静态类型 Base*
,调用 Get
函数会导致返回具有静态类型 ReturnTypeBase*
的指针。由于这是一个重写的虚函数,派生的 class 的 Get
函数将如您所愿地被调用,并且返回的指针实际上指向一个 ReturnTypeDerived1
对象,但是编译器无法证明这一点。你需要演员表:
auto one = static_cast<ReturnTypeDerived1*>(objects[0]->Get());
auto two = static_cast<ReturnTypeDerived2*>(objects[1]->Get());
如果您将 ReturnTypeBase
设为多态类型,您可以在此处使用 dynamic_cast
来避免在动态类型错误时出现未定义的行为。
如前所述,您将在 .Get() 调用中遇到编译器错误。
如果你想避免这种情况,请分配给 base class..
ReturnTypeBase * one = objects[0].Get();
ReturnTypeBase * two = objects[1].Get();
只要您通过基class中定义的抽象方法(例如'toString()'方法)访问'one'和'two',您就不会内部数据有问题。
如果您打算在基础 class 的所有实例中对数据进行相同处理,您可能需要考虑改用模板 class。
参考这个问题:C++ virtual function return type
让我们考虑以下一组对象。
class ReturnTypeBase
{
};
class ReturnTypeDerived1 : public ReturnTypeBase
{
public:
int x;
};
class ReturnTypeDerived2 : public ReturnTypeBase
{
public:
float y;
};
class Base
{
public:
virtual ReturnTypeBase* Get() = 0;
};
class Derived1: public Base
{
public:
virtual ReturnTypeDerived1* Get()
{
return new ReturnTypeDerived1();
}
};
class Derived2: public Base
{
public:
virtual ReturnTypeDerived2* Get()
{
return new ReturnTypeDerived2();
}
};
这些对象可以按以下方式使用吗?
Base* objects[2];
objects[0] = new Derived1();
objects[1] = new Derived2();
ReturnTypeDerived1* one = objects[0]->Get();
ReturnTypeDerived2* two = objects[1]->Get();
我假设因为 return 类型是协变的(?),上面的对象集是合法的 C++。是否会调用适当的 Get() 方法?指针 one/two 是否可以在不强制转换的情况下分配给 Get() 方法的 return 值?
代码将不会像编写的那样编译。因为 objects[0]
具有静态类型 Base*
,调用 Get
函数会导致返回具有静态类型 ReturnTypeBase*
的指针。由于这是一个重写的虚函数,派生的 class 的 Get
函数将如您所愿地被调用,并且返回的指针实际上指向一个 ReturnTypeDerived1
对象,但是编译器无法证明这一点。你需要演员表:
auto one = static_cast<ReturnTypeDerived1*>(objects[0]->Get());
auto two = static_cast<ReturnTypeDerived2*>(objects[1]->Get());
如果您将 ReturnTypeBase
设为多态类型,您可以在此处使用 dynamic_cast
来避免在动态类型错误时出现未定义的行为。
如前所述,您将在 .Get() 调用中遇到编译器错误。 如果你想避免这种情况,请分配给 base class..
ReturnTypeBase * one = objects[0].Get();
ReturnTypeBase * two = objects[1].Get();
只要您通过基class中定义的抽象方法(例如'toString()'方法)访问'one'和'two',您就不会内部数据有问题。
如果您打算在基础 class 的所有实例中对数据进行相同处理,您可能需要考虑改用模板 class。