Mik*_*ang 6 c++ inheritance downcast
我想在不更改现有类的情况下添加额外的功能。
说,
class base{
public:
int i;
base(){i = 1;}
virtual void do_work(){ /*Do some work*/ }
};
Run Code Online (Sandbox Code Playgroud)
如果我想serialization向其中添加成员函数,我只需创建一个派生类
class derived : public base{
public:
void serialize();
};
void derived::serialize(){
cout << "derived class" << endl;
}
Run Code Online (Sandbox Code Playgroud)
我确实需要处理现有的base对象,例如
int main(){
base a;
derived & b = static_cast<derived &>(a);
b.serialize();
}
Run Code Online (Sandbox Code Playgroud)
这个例子运行没有问题。但我确实知道一般情况下应该避免这种downcast情况static_cast。
但我想知道对于downcast这一特定用例是否可以被认为是安全的,因为该类derived只有一个额外的成员函数。它是否会有一些潜在的未定义的访问行为vtable?
您扩展的方式Base没有利用,vtable因为您没有virtual方法。将其视为更容易Derived has A Base;您创建了一个包含Base成员变量的新类。
我的建议。
模板函数
我个人会选择模板函数。您可以将所有工作保留在原始问题中,并避免virtual向类添加调用。
template<typename T>
void serialize_object(T& t)
{
t.serialize()
}
Run Code Online (Sandbox Code Playgroud)
然后根据你的例子。
Derivied d;
serialize_object(d);
Run Code Online (Sandbox Code Playgroud)
最大的好处是您无需在此处添加运行时强制转换。如果您传递一个没有方法的对象,编译器会通知您serialize。
走向虚拟
如果您确实想通过虚拟接口来处理此问题,请这样做。
struct Serializable{
virtual void serialize()=0;
virtual ~Serializable(){}
}
class Derived : public Serializable {
public:
void serialize() override;
}
void Derivied::serialize()
{
std::cout << "Yah\n";
}
Run Code Online (Sandbox Code Playgroud)
然后在你的代码中。
Derivied d;
Serializable& s = dynamic_cast<Serializable&>(d);
Run Code Online (Sandbox Code Playgroud)
然而,这里最大的问题是谁是你的基类的所有者?他们提供虚拟医生吗?如果没有,那么使用std::unique_ptrorstd::shared_ptr可能会导致您无法直接处理该接口。
您不能只将基类对象强制转换为继承类。继承类中的任何成员都不会被创建和初始化。您需要从继承类的对象开始。
当然,您可以采用另一种方式,从从基类继承的类的函数中调用基类函数,因为根据定义,基类对象将始终作为继承的类对象的一部分存在。
如果您有一个指向基类的指针,并且使用 RTTI 进行构建,则可以使用dynamic_cast 来转换为继承的类,但如果该对象不属于您尝试转换为的类,则该转换将失败并返回 NULL 。但通常调用虚函数比使用dynamic_cast更好。