C ++继承。更改对象数据类型

时间:2011-11-07 15:09:18

标签: c++

我在强制数据类型更改时遇到了问题。我有一个基类说A和两个派生自A的类BC。我将对象BC传递给一个函数,该函数检查它是哪种类型的对象(BC)。下面是一些示例代码以及我的问题:

enum ClassType {"B", "C"};

class A {
  protected:
     m_Type;

  public:
     ClassType Type() { return m_Type}
     ...
     ...
};

class B : public A {
   otherMemberFunctions();

}

 class C : public A {
   otherMemberFunctions();

}


void WhatType(vector<A*>* candidates){


  vector<B*> b_candidates(0);
  vector<C*> c_candidates(0);

  for(int i = 0; i < candidates->size(); i++){

    if(candidates->at(i)->Type() == B ){

      B* b = (B*) candidates->at(i);
      b_candidates(b);
   }

  //Same idea for Object C
  }
}

然后我会使用WhatType(vector<A*>* candidates),如下所示

vector<B*>* b_example

WhatType((vector<A*>*) b_exmaple)

当我在函数vector中填写新的WhatType b_candidates时。我仍然可以访问B对象中的成员函数,还是只能访问基类A中的成员函数?

当我改变对象的类型时,我对该对象会发生什么感到困惑。

下面

WhatType((vector<A*>*) b_exmaple)

在这里

B* b = (B*) candidates->at(i);

5 个答案:

答案 0 :(得分:1)

由于您转为B*,您可以访问B个成员。

答案 1 :(得分:1)

当然,对象的实际类型不会改变,但如果您只有基类的指针(或引用),则无法访问特定于子类的字段。

访问子类字段的方法是使用dynamic_cast将其强制转换为子类:

A *a = new B;  // We cant reach the members of class B in a
B *b = dynamic_cast<B *>(a);  // But now we have a proper pointer to B

答案 2 :(得分:1)

好的,所以如果你有一个类型为B的对象在堆上实例化并由类型为A的指针持有。您只能看到类型A的成员函数,才能访问B所需的static_cast<B*>类成员函数,这就是......“(B*) “ ... 是在做。

dynamic cast更好,因为如果无法进行转换,它将返回null。但当然它发生在运行时间,所以有一个惩罚。

答案 3 :(得分:1)

当你收到一个指向多态对象的指针时,你有两种类型:对象的“静态”类型,在你的情况下,它将是A *,它的“动态”或“真实”类型,这取决于实际分配给它的内容。

A *强制转换为B *会强制编译器将该指针视为指向B的指针;只要您确实知道指针实际上是指向B 的指针,这是安全的,否则编译器将开始编写无意义的代码(在另一个数据上调用B方法类型)。

您尝试实现的检查是RTTI的本地版本,这是一种机制,可以让您知道哪个是指针的“实际类型”或对多态类的引用,并执行这种类型的安全地施放。有关它的更多信息,请查看C ++手册中的typeiddynamic_cast。 (顺便提一下,IIRC dynamic_cast不仅仅是为了安全,以防动态类型错误,但如果你在复杂的类层次结构中使用它,它也可能会对你的指针执行一些额外的魔法;所以,避免使用C风格的转换多态类)

顺便说一下,通常认为“代码气味”必须手动检查指针的“真实类型”才能投射它并使用它的方法:OOP理想只能完成工作虽然基类中有virtual个方法。


大警告: RTTI仅对多态类工作,即至少有一个虚拟方法的类。另一方面,如果你正在构建一个类层次结构,其中对象作为指向基类的指针传递,你几乎肯定希望有一个virtual析构函数,所以这没什么大不了的。

答案 4 :(得分:-1)

由于BCÀ派生的,vector<B *>vector<C *>包含A基类对象。如果您确保在构造函数中设置A::m_Type属性,则不会出现问题:

enum ClassType {'B', 'C'};    // see I modified your definition

class A {
    protected:
         ClassType m_Type;

    public:
         ClassType Type() { return m_Type};
    ...
    ...
};

class B : public A {
    public:
         B() : m_Type('B') {}
         ....
};

使用此功能,您可以毫无问题地检查BC个对象。之后,当您将基础对象转换为派生对象时,您将完全访问其公共方法和属性。