c++继承.更改对象数据类型
C++ Inheritance. Changing Object data Types
我在强迫自己的对象更改数据类型时遇到了麻烦。我有一个基类,叫做A
,还有两个从A
衍生出来的类,叫做B
和C
。我将对象B
和C
传递给一个函数,该函数检查对象的类型(B
或C
)。下面是一些示例代码和我的问题的问题:
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)
当我在函数WhatType
中填充了新的vector
b_candidate时。我是否仍然可以访问B
对象中的成员函数,还是只能访问基类A
中的成员函数?
我很困惑,当我改变对象的类型时,对象会发生什么。
这里WhatType((vector<A*>*) b_exmaple)
和
B* b = (B*) candidates->at(i);
当你收到一个指向多态对象的指针时,你有两种类型:对象的"静态"类型,在你的情况下,将是A *
,以及它的"动态"或"真实"类型,这取决于实际分配给它的内容。
将A *
转换为B *
强制编译器将该指针视为指向B
的指针;这是安全的,只要你知道指针实际上是指向B
的指针,否则编译器将开始编写无意义的代码(在其他类型的数据上调用B
方法)。
您正在尝试实现的检查是RTTI的一个本地版本,这是一种机制,允许您知道哪个是指针的"真实类型"或对多态类的引用,并安全地执行这种类型的强制转换。查看c++手册中的typeid
和dynamic_cast
以获得更多信息。(顺便说一句,IIRC dynamic_cast
不仅是为了在动态类型错误的情况下的安全,而且如果你在复杂的类层次结构中使用指针,它可能还会对指针执行一些额外的魔法;因此,避免多态类的c风格强制转换)
顺便说一下,通常认为必须手动检查指针的"真实类型"才能强制转换它并使用它的方法是"代码气味":OOP理想情况下只能通过基类中可用的virtual
方法来完成工作。
重大警告:
RTTI只在多态类上工作,即至少有一个虚方法的类。另一方面,如果您正在构建一个类层次结构,其中对象作为指向基类的指针被传递,那么您几乎肯定希望有一个virtual
析构函数,所以这没什么大不了的。
由于您强制转换为B*
,您将可以访问B
的成员
对象的实际的类型当然不会改变,但是如果你只有一个指向基类的指针(或引用),你就不能访问特定于子类的字段。
要访问子类字段,可以使用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
如果在堆上实例化了一个类型为B
的对象并由类型为A
的指针持有。你只能看到A
类型的成员函数,要访问B
类型的成员函数,你必须访问static_cast<B*>
,也就是…"( B*
)"……在干什么。
dynamic cast
更好,因为如果转换不可能,它将返回null
。当然,这是在运行时发生的,所以有惩罚
由于B
和C
是À
的派生,因此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') {}
....
};
使用这个,您将检查您的B
和C
对象没有问题。之后,当您将基对象转换为派生对象时,您将可以完全访问它们的公共方法和属性。
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 类对象在 c++ 中是否具有数据类型?
- 指针数据类型变量如何包含对象?
- 如果在 C++ 构造函数中以错误的顺序初始化对象数据,会发生什么类型的错误
- 如何访问从 COM 对象返回的 VARIANT 数据类型中的安全数组C++?
- 使用各种数据类型成员创建对象的简便方法
- 具有临时对象的 Fundamenta 数据类型赋值运算符
- 使用MPI/OpenMP的C 程序带有派生数据类型(嵌套类对象)容器
- 如何掩盖对象数组的数据类型字符串到C 中的INT
- 将任何数据类型/对象作为参数传递以确定其大小
- 通用B树,用于存储自定义对象/数据类型
- 基本数据类型变量 VS 对象变量
- 使用两种或两种以上数据类型的对象作为c++映射、OOP的关键字
- 如何在一个向量中存储具有不同数据类型的对象
- 将对象强制转换为数据类型
- 数据类型与模板参数不同的模板对象
- 从数据库中以 blob 数据类型形式存储的原始图像数据中检索 CImage 对象
- C++-将模板类型对象强制转换为特定的数据类型
- 在构造子类对象的过程中,更改一个类属性的数据类型会导致segfault
- c++继承.更改对象数据类型