好的,这是一个让我如此困惑的简单例子......
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在“new int”时为int分配内存 但我不知道我应该如何阅读新的Third();因为它是构造函数
Second * secondptr = thirdptr; / First * firstptr = secondptr; 这两个陈述令人困惑。 任何人都可以用&amp;运算符或简单的单词将其与地址运算符相关联 我理解了这个指针和继承的概念,但这部分令人困惑。
我应该如何从第二个例子中得到结果? 我正在读的那本书正在说
为第一个例子 //关于指针算术运算的C ++编译器做出决定 //基于指针的类型,而不是指针实际指向
的内容第二个例子 //虚拟功能:决定,而不是基于指针类型 //,根据指针实际指向的内容调用什么
这是翻译,所以可能不准确,但仍然无法理解。 如果你能帮助我,我将非常感激!
答案 0 :(得分:0)
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()
。这通常使用virtual function table。
答案 1 :(得分:0)
要回答您的第一个问题,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;
注意所有三个指针都指向同一块内存。 (另请注意,指针都指向内存的 start - 完全相同的位置。上面描述的很难。)
至于你的第三个问题:
决定,不是基于指针类型,根据什么来调用什么 指针实际指向
表示编译器将根据内存中对象的实际类型决定调用哪个函数实例,而不是指向内存的指针类型。因此,在您的示例中,您创建了一个类型为Third
的对象,并且有三个指针指向它,类型为First
,Second
,Third
。但是,无论指针类型如何,因为Func
是虚拟的,所以Third
的{{1}}版本被执行,因为内存中的对象是Func
类型。