虚函数, ->运算符, 继承如此混乱
virtual function, -> operator, inheritance SO CONFUSING
好吧,这是一个简单的例子,让我很困惑…
class First { public: void Func() {cout<<"FirstFunc";} };
class Second : public First
{ public: void Func() {cout<<"SecondFunc";} };
class Third : public Second
{ public: void Func() {cout<<"ThirdFunc";} };
int main () {
Third * thirdptr = new Third();
Second * secondptr = thirdptr;
First * firstptr = secondptr;
firstptr->Func(); // prints out FirstFunc
secondptr->Func(); // prints out SecondFunc
thirdptr->Func(); // prints out ThirdFunc
delete thirdptr;
这是虚函数
class First { public: virtual void Func() {cout<<"FirstFunc";} };
class Second : public First
{ public: virtual void Func() {cout<<"SecondFunc";} };
class Third : public Second
{ public: virtual void Func() {cout<<"ThirdFunc";} };
int main () {
Third * thirdptr = new Third();
Second * secondptr = thirdptr;
First * firstptr = secondptr;
firstptr->Func(); // prints out ThirdFunc
secondptr->Func(); // prints out ThirdFunc
thirdptr->Func(); // prints out ThirdFunc
delete thirdptr;
好的,这是我的问题。
如何读取Third * thirdptr = new Third();New为int分配内存,当" New int"但我不知道我应该如何阅读新的第三();因为它是构造函数
Second * secondptr = thirdptr;/First * firstptr = secondptr;这两个表述太令人困惑了。有人能用&操作符还是与地址操作符相关的简单词语?我理解了这个指针和继承的概念,但是这部分太混乱了。
我应该如何从第二个例子中得到结果?我在读的那本书上面写着
作为第一个例子//c++编译器对于指针的算术运算,做出一个决定//基于指针的类型,而不是指针实际指向的
作为第二个例子//虚拟函数:决定,不基于指针类型//根据指针实际指向的对象调用
这是翻译,所以可能不准确,但仍然无法理解。如果你能帮助我,我将非常感激!
-
new Third()
做两件事。首先为Third
对象分配内存,然后调用Third
对象的构造函数。您可以将语句分为两部分,new Third
分配内存,()
调用构造函数。 -
Second * secondptr = thirdptr; / First * firstptr = secondptr;
这三个变量都被赋值给同一个指针。假设thritptr
等于100。那么在这些语句结束时,secondptr
和firstptr
都等于100。所有三个指针都指向内存中的同一地址。然而,由于它们是不同的类型,所以编译器对它们的解释不同 -
对于非虚函数,方法调用在编译时根据变量的类型进行解析。因此,在编译第一个代码时,
firstptr
的类型是First*
,因此编译器生成对First::Func()
的调用。对于虚函数,直到运行时才完全解析方法调用。编译器生成的代码将确定变量指向的实际类型并调用该函数。在第二个示例中,当程序运行时,firstpr->Func()
首先确定firstptr
确实指向Thrird
对象,因此调用Third::Func()
。
回答你的第一个问题,new Third()
在高层次上做着与new int
相同的事情。正如您所说,new int
将为int
分配内存,并且左侧的指针将指向该内存。new Third()
为Third
对象分配内存,并使用Third
类的默认构造函数Third()
来初始化它。
对于你的第二个问题,你正在创建三个指针,并将它们都指向同一个内存块。我相信,由于继承,可以隐式地将每个指针类型强制转换为更高的类型(隐式强制转换意味着没有显式指令,例如static_cast
或c风格强制转换)。视觉:
----
| | <-- Some block of memory.
----
A -> ---- <-- A* aptr = new A();
| |
----
A -> ----
B -> | | <-- B* bptr = aptr;
----
A -> ----
B -> | |
C -> ---- <-- C* cptr = bptr;
注意这三个指针是如何指向同一个内存块的。(还要注意,所有指针都指向内存的起始——完全相同的位置。很难在上面描述
关于你的第三个问题:
不是根据指针类型决定调用什么,而是根据指针类型决定调用什么指针实际上指向
意味着编译器将根据内存中对象的实际类型来决定调用函数的哪个实例,而不是根据指向内存的指针的类型。因此,在您的示例中,您创建了一个类型为Third
的对象,并有三个指针指向它,类型为First
, Second
, Third
。不管指针类型是什么,因为Func
是虚拟的,所以Third
版本的Func
会被执行,因为内存中的对象类型是Third
。
- 通过继承类使用来自不同命名空间的运算符
- 运算符继承和 cpp 核心准则 c.128 的问题
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- 继承模板化转换运算符
- C++ 继承运算符=
- 在继承的模板类中使用下标 [] 运算符
- 如何调用继承的重载运算符<<并在派生类的输出中添加更多文本?
- C++模板化类上继承的运算符'<<'
- 类继承和运算符重载
- 通过继承重载运算符会导致歧义
- 使用继承的指针列表复制构造函数或重载运算符=
- C++中移动赋值运算符的继承
- 如何在C++上的多个继承上下文上使用特定基类中的运算符
- 继承类中的比较运算符
- 继承 C++14 中的模板化运算符 =:g++ 和 clang++ 的不同行为
- 具有继承的未声明标识符(运算符 ostream)
- 如何使用运算符编写可继承的模板类
- C++继承运算符<<
- 继承运算符 +()
- 继承运算符*的问题