c++中的向上和向下转换
Upcast and Downcast in C++
class file {
std::string name;
};
class directory : public file {
std::vector<file*> entries;
};
directory d;
file f;
f = d; // Only d.name is copied to f; entries are lost
如果我们这样做:
directory* dp = new directory;
file* fp ;
fp = dynamic_cast<file*>(dp);
保留条目和标识作为目录对象,否则仍然只有dp->name
被复制到f
;条目丢失
还有,downcast是如何工作的?
如果我们这样做会发生什么:
dp = dynamic_cast<dp*> (fp);
我将尽量简单地解释,但是您仍然应该阅读更多关于这方面的文档。
directory d;
file f;
f = d; // Only d.name is copied to f; entries are lost
这是因为目录和文件的类型和大小不同。文件大小为sizeof(file)
,目录为sizeof(directory)
,大于sizeof(file)
。即使是原始内存复制也只会将目录的文件部分复制到file对象,如果您打算复制更多,则会产生未定义的行为。
directory* dp = new directory;
file* fp ;
fp = dynamic_cast<file*>(dp);
首先,动态强制转换在这里不起作用,因为这些不是多态类型。如果有,这些就只是指针。由于目录is-a
文件,您可以使用文件指针指向目录。对象在相应的位置。但是,您不能通过文件指针访问独占目录成员,除非进行反类型转换。
dp = dynamic_cast<dp*> (fp);
您将重新获得对原始指针的目录成员访问权,如上所述。
下面是关于什么是上型和下型的解释:questionscompiled.com
向上转型:向上转换是将派生类类型的指针或引用转换为基类类型的指针或引用,在继承树中向上。提升有助于实现c++中的接口概念。当函数在基类类型指针或引用(指向或引用它的某些派生类)上被调用时,将调用该派生类的正确成员函数。
向下类型转换:向下转换是将基类类型的指针或引用转换为其派生类的指针或引用类型,在继承树中向下。这是在dynamic_cast操作符的帮助下实现的,该操作符在运行时安全地向下转换。
下面是一个例子:
class A
{public:
int i;
virtual void show(){}
};
class B:public A
{
public:
int j;
virtual void show() { cout<<"B"; }
};
int main()
{
A* ptr=new B; // UPCASTING
B* ptrb;
ptrb=dynamic_cast<B*>(ptr); //DOWNCASTING to derived object
ptrb->show(); // upcasting helped in implementing interface
}
参考上面的例子,dynamic_cast确保ptr指向B类型的对象或其子类。
继承捕获了"is a"的关系。考虑到你的问题的上下文,下面的话不太明智:
class directory : public file
仅仅因为目录和文件都有名称并不意味着directory "is a" file
。如果说file "is a" directory
.
这里还有许多其他的推理方法。例如,您可以认为文件和目录都是thing_that_has_a_name
:
class thing_that_has_a_name {
std::string name;
/* ... */
};
class file : public thing_that_has_a_name {
/* ... */
};
class directory : public thing_that_has_a_name {
std::vector<file*> entries;
/* ... */
};
(这是一种方法,但是继承是一种相当严厉的机制。如果你正在为"有一个名字"这样的抽象概念创建基类,那么你很快就会发现自己需要继承多个基类。
回到您所看到的技术方面,您必须记住的是,创建新对象与与现有文件或目录对象作为thing_that_has_a_name
接口之间有很大的区别。如果你做过这样的声明:
directory d;
file f;
这些是实例化。运行构造函数。无论目录的sizeof
是多少,这就是d
刚刚获得的内存。不管sizeof
文件是什么,这就是f
刚刚得到的。然而:
thing_that_has_a_name& tthan_ref_to_d (d);
thing_that_has_a_name* tthan_ptr_to_f (&f);
仅仅分别创建一个引用和指针,通过它们,您可以通过在目录和文件对象的基类中指定的接口与它们进行交互。像这样的"向上"(称为"向上",因为您正在向根爬上类层次结构)是相对安全的……而不是你做错了什么。
另一方面,"Downcasting"可能是危险的。我们知道每个directory
和file
都可以被视为thing_that_has_a_name
…然而,如果你有一个指向thing_that_has_a_name
的指针或引用,那么任意代码都不能确定它是directory
还是file
。有一些方法可以插入条件代码来检查和确定,但这通常被认为是你在设计中做错了的标志:
其他人已经提供了更多的细节,所以我就到此为止,但只是把它放在那里,如果你发现一些有用的
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中使用nlohmann从类到json的转换
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- 复制列表初始化的隐式转换的等级是多少
- 正在将指针转换为范围
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 是否可以从int转换为enum类类型
- 了解 GLM- openGL 中的相机转换
- 将无符号char*转换为std::istream*C++