我有点困惑。在C ++中,您可以分配指向基类的派生类的地址吗?反过来怎么样? [英] I am a little confused. In C++, can you assign the address of a derived class pointed to the base class? How about vice versa?

查看:116
本文介绍了我有点困惑。在C ++中,您可以分配指向基类的派生类的地址吗?反过来怎么样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

1。你可以将派生类的对象的地址分配给指向基类的指针吗?



2.你能指定一个基类对象的地址吗?指向派生类的指针?



我尝试过:



我试着读一本充满错误和令人困惑的解释的书。

1. Can you assign the address of an object of a derived class to a pointer to the base class?

2. Can you assign the address of an object of a base class to a pointer to the derived class?

What I have tried:

I tried reading a book full of errors and confusing explanations.

推荐答案

如果你想象究竟发生了什么,这实际上很容易理解。



首先,您必须了解编译时和运行时类型。变量被声明为某种基类型,但它可以在运行时引用派生类型的对象。



为什么反之亦然?这很简单。因为派生类型是扩展,而不是减少。比如,一些基类Base有成员A和B.派生类Derived添加了一些成员C,所以它有A,B和C.



如果您的变量属于编译时类型(声明为)Base,则允许您访问A和B.当您引用Derived时,它也有C,但它仍然有A和B,所以你是安全的。



想象一下,你将变量声明为Derived,但你设法为它分配了一个Base实例。 (这里,我在指针或实例本身之间没有区别,这个想法是一样的。)然后编译器不仅可以访问A和B,还可以访问C;运行时期间不存在和C.想象一下会发生什么:你可以访问对象之外的内存。



OOP的整个想法是基于使用某些基类变量引用的派生类。为了实现多态性,使用虚函数机制。但在极少数情况下,我们可能需要通过使用基类型变量并将引用的对象解释为某种派生类型的对象来稍微违反纯OOP。显然,这并不总是可行的,因此您首先需要确保实际的运行时对象与您要解释的类型兼容。 (如果没有,你只需跳过操作。)为此,C ++具有 dynamic_cast 这样的功能:类型转换 - C ++教程 - 动态转换 [ ^ ]。



这也称为向下投射。我想重新迭代:它不应该定期使用。通常,它被用作一些OOP设计的修复,它最初没有考虑到某些要求,即不正确,但重新设计它是不可行的。还有其他情况,但它们不应被视为常规技术。



-SA
It's actually easy to understand if you imagine what exactly happens.

First of all, you have to understand that there are compile-time and runtime types. A variable is declared as some base type, but it may reference an object of a derived type during runtime.

Why not visa versa? It's easy. Because derived types are extended, not reduced. Say, some base class "Base" has members A and B. A derived class "Derived" adds some member C, so it has A, B and C.

If your variable is of the compile-time type (is declared as) "Base", you are allowed to access A and B. When you reference "Derived", it also has C, but it still has A and B, so you are safe.

Imagine that you have the variable declared as "Derived", but you managed to assign an instance of "Base" to it. (Here, I don't make difference between assignment of pointers or instances themselves, the idea is the same.) Then the compiler can access not only A and B, but also C; and C does not exist during runtime. Imagine what can happen: you can access memory beyond the object.

The whole idea of OOP is based on working with derived classed referenced by variable of some base classes. To achieve polymorphism, virtual function mechanism is used. But in rare case we may need to violate "pure" OOP a bit, by having a base-type variable and interpreting the referenced object as an object of some derived type. Apparently, this is not always possible, so you first need to make sure that the actual runtime object is compatible with the type you want to interpret is as. (If not, you just skip the operations.) For this purpose, C++ has such a feature as dynamic_cast: Type conversions — C++ Tutorials — dynamic cast[^].

This is also called down-casting. I want to re-iterate: it should not be used on regular basis. Often, it's used as fix to some OOP design which initially did not take into account some requirements, that is, is incorrect, but it's not feasible to redesign it. There are other cases, but they should not be taken as regular technique.

—SA


谢尔盖的答案是正确的,但对初学者来说并不是很容易阅读。以下是您的问题的简短版本:



(1)是 - 因为派生对象始终可以被视为其基类



(2)仅当指针指向的对象确实是派生类时。由于编译器通常不能确定在编译时,您必须显式地将指针强制转换为派生对象。这被称为向下投射。



您有三个选项可以确保对象确实是您要投射到的派生类:



(a)作为程序员,你知道在任何情况下它都会成为这样一个对象。 (希望你是对的。如果没有,你的程序可能会崩溃。)



(b)你明确地将对象的类型存储在基类的成员中(不是很优雅而且不像OOP一样)



(c)您让编译器存储有关对象的运行时信息(在编译器中启用运行时类型信息)选项)。在这种情况下,您可以使用动态强制转换,如果对象不是预期类型,它将返回NULL指针,例如:

Sergey's answer is correct, but not really easy to read for a beginner. Here is the short version to your question:

(1) YES - Because a derived object can always be treated as its base class

(2) Only if the object that the pointer points to is indeed of the derived class. As the compiler can in general not determine that at compile time, you must explicitly cast the pointer to the derived object. That is called "down casting".

You have three options to make sure that the object is indeed of the derived class you want to cast to:

(a) You as programmer know that under any circumstance it will be such an object. (Hopefully you are correct. If not, your program is likely to crash.)

(b) You store the type of object explicitly in a member of the base class (not very elegant and not really OOP-like)

(c) You let the compiler store runtime information about your objects (enable "runtime type information" in your compiler options). In that case you can use a dynamic cast, which will return a NULL-pointer if the object is not of the expected type, for example:
BaseClass* pBase = ....;
DerivedClass* pDerived = dynamic_cast<derivedclass*> (pBase);
if (pDerived != 0)
{
   // yes - pBase was really pointing to a DerivedClass object
   // an now we can use pDerived to access the derived class's members
   .....
}


这篇关于我有点困惑。在C ++中,您可以分配指向基类的派生类的地址吗?反过来怎么样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆