class test1 { public: virtual void func1() { cout << "test1-func1" << endl; } virtual void func2() { cout << "test1-func2" << endl; } }; class test2 { public: virtual void func2() { cout << "test2-func2" << endl; } virtual void func1() { cout << "test2-func1" << endl; } }; test2 * ptr = (test2 *)&t1; ptr->func1(); 为什么输出test2-func2
时间: 2023-03-30 13:03:18 浏览: 92
我可以回答这个问题。这段代码是一个简单的 C++ 多态示例,其中有两个类 test1 和 test2,它们都有两个虚函数 func1 和 func2。ptr 是一个指向 test2 类的指针,通过强制类型转换将其指向 test1 类的对象。这样,当调用 ptr 的 func1 函数时,实际上会调用 test2 类的 func1 函数,因为它是虚函数并且在 test2 类中被重写了。而调用 ptr 的 func2 函数时,会调用 test1 类的 func2 函数,因为它在 test1 类中被定义。
相关问题
接下来,我们看一个练习,大家思考一下,会输出什么呢?#include <iostream> using std::cout; using std::endl; class A{ public: virtual void func(int val=1){ cout << "A->" << val << endl; } virtual void test(){ func(); } private: long _a; }; class B :public A{ public: virtual void func(int val = 10){ cout << "B->" << val << endl; } private: long _b; }; int main() { B b; A* p1 = (A*)&b; B* p2 = &b; p1->func(); p2->func(); return 0; } 为什么输出B->1,B->10
这段代码的输出结果是 "B->1" 和 "B->10"。
在这段代码中,存在一个虚函数 func(),它在类 A 和类 B 中被重写。类 A 中的 func() 函数有一个默认参数值为 1,而类 B 中的 func() 函数有一个默认参数值为 10。
在主函数中,先创建了一个对象 b,然后分别用指向 A 类型的指针 p1 和指向 B 类型的指针 p2 分别指向对象 b。
当调用 p1->func() 时,由于 p1 的类型是 A*,因此会调用类 A 中的虚函数 func()。由于虚函数的动态绑定特性,实际上会调用类 B 中的 func()。但是,由于虚函数不参与默认参数的动态绑定,所以调用时使用了类 A 中默认参数值 1,输出结果为 "B->1"。
当调用 p2->func() 时,由于 p2 的类型是 B*,因此直接调用类 B 中的 func() 函数。此时使用的默认参数值是类 B 中定义的值 10,输出结果为 "B->10"。
#include <iostream> using namespace std; class Base { public: virtual void Func1(uint32_t p = 100) { cout << p << endl; } void Func2(uint32_t p = 100) { cout << p << endl; } }; class Derive : public Base { public: void Func1(uint32_t p = 200) { cout << p << endl; } void Func2(uint32_t p = 200) { cout << p << endl; }; int main(void) { Base *d = new Derive(); d->Func1(); //因为基类和派生类函数参数不一样,所以不构成覆盖 d->Func2(); //基类中Func2没有virtual关键字,不构成覆盖 return 0; }
在上述代码中,有两个函数`Func1()`和`Func2()`,分别位于基类`Base`和派生类`Derive`中。我们来逐个分析它们的特点和调用情况:
1. `Func1()`函数:
- 基类`Base`中的`Func1()`函数是虚函数,可以被派生类覆盖。
- 派生类`Derive`中的`Func1()`函数与基类中的函数具有相同的名称和参数类型,但有一个默认参数值不同。
- 在`main()`函数中,使用基类指针`d`指向派生类对象,并调用`d->Func1()`。
- 由于基类和派生类的函数参数不一样(派生类中有一个默认参数值为200),所以这里不构成覆盖。实际上调用的是基类中的`Func1()`函数,默认参数值为100。
2. `Func2()`函数:
- 基类`Base`中的`Func2()`函数没有使用虚函数关键字,不是虚函数,无法被派生类覆盖。
- 派生类`Derive`中的`Func2()`函数与基类中的函数具有相同的名称和参数类型,但有一个默认参数值不同。
- 在`main()`函数中,使用基类指针`d`指向派生类对象,并调用`d->Func2()`。
- 由于基类中的`Func2()`函数不是虚函数,不构成覆盖,实际上调用的是基类中的`Func2()`函数,默认参数值为100。
因此,执行上述代码的输出结果是:
```
100
100
```
需要注意的是,在派生类中重新定义虚函数时,最好避免改变函数的参数列表,以确保能正确覆盖基类的虚函数。默认参数值的不同并不影响函数的覆盖关系。