多态
判断
-
Q1: 虚函数可以是内联的? A1: 错误。内联是编译时刻决定的,虚函数是运行时刻动态决定的,所以虚函数不能是内联函数。虚函数前加上inline不会报错,但是会被忽略。
-
Q2: 一个类内部,可以同时声明
static void fun()
和virutal void fun()
两个函数? A2: 错误。虽然静态函数不存在this指针,但是还是不能声明同参的虚函数和静态函数。 -
Q3: 基类的析构函数非虚,派生类的析构函数是虚函数。delete派生类指针(指向派生类对象)会调用基类析构函数? A3: 正确。
通过派生类指针,删除派生类对象时,无论父类析构函数是不是虚函数,都会调用基类析构函数。
通过基类指针,删除派生类对象时,是否调用基类析构函数,取决于基类析构函数是否是virtual函数
知识点
可以通过对象名主动调用析构函数,主动调用构造函数会出错。
如果类中声明了构造函数(无论是否有参数),编译器便不会再为之生成隐含的构造函数。
构造函数不能是虚函数,析构函数可以是虚函数。
编程
析构函数需要声明为virtual
1#include <iostream>
2using namespace std;
3
4int g_num = 0;
5
6class Base
7{
8public:
9 Base() {}
10 ~Base() { g_num += 1; }
11};
12
13class Derived:public Base
14{
15public:
16 Derived() {}
17 ~Derived() { g_num += 2; }
18};
19
20int main()
21{
22 Base *p = new Derived();
23 delete p;
24 cout << g_num << endl;
25 return 0;
26}
27// 输出:1
动态绑定依赖于指针或者引用
1#include <iostream>
2using namespace std;
3
4class Base
5{
6public:
7 virtual void fun() {cout << "base" << endl;}
8};
9
10class Derived:public Base
11{
12public:
13 virtual void fun() { cout << "derived" << endl;}
14};
15
16void func1(Base &obj) {
17 obj.fun();
18}
19void func2(Base obj) {
20 obj.fun();
21}
22
23int main()
24{
25 Base *pBase = new Derived();
26 func1(*pBase); // derived
27 func2(*pBase); // base
28 return 0;
29}
operator可以定义为虚函数
1#include <iostream>
2using namespace std;
3
4class Base
5{
6public:
7 virtual void operator == (int val2) {
8 cout << "base: " << val2 << endl;
9 }
10};
11
12class Derived:public Base
13{
14public:
15 virtual void operator == (int val2) {
16 cout << "derived: " << val2 << endl;
17 }
18};
19
20int main()
21{
22 Base *pBase = new Derived();
23 Derived *pDerived = new Derived();
24 *pBase == 10;
25 *pDerived == 20;
26}
27
28// derived: 10
29// derived: 20
绝不重新定义继承而来的缺省参数
1#include <iostream>
2using namespace std;
3
4class Base
5{
6public:
7 virtual void fun(string str = "base123") {
8 cout << str << endl;
9 }
10};
11
12class Derived:public Base
13{
14public:
15 virtual void fun(string str = "derived") {
16 cout << str << endl;
17 }
18};
19
20int main()
21{
22 Base *pBase = new Derived();
23 pBase->fun(); // base123
24}
同名const函数属于有效重载
1#include <iostream>
2using namespace std;
3
4class Base
5{
6public:
7 void func1() {cout << "non-const\n";}
8 void func1() const {cout << "const\n";}
9};
10
11int main()
12{
13 Base b1;
14 b1.func1(); // non-const。非常量对象也可以调用const函数,此处优先调用non-const函数
15
16 const Base b2;
17 b2.func1(); // const。常量对象只能调用const函数
18}
virtual函数的const必须统一
1#include <iostream>
2using namespace std;
3
4class Base
5{
6public:
7 virtual void display() const { cout << "Base"; }
8};
9
10class Derived:public Base
11{
12public:
13 virtual void display() { cout << "Derived"; }
14};
15
16int main()
17{
18 Base *pBase = new Derived();
19 pBase->display(); // Base
20}
派生类生成过程
派生类构造函数执行顺序:
1.调用基类构造函数,调用顺序按照它们被继承时声明的顺序(从左向右)
2.对派生类新增的成员对象初始化,调用顺序按照它们在类中声明的顺序
3.执行派生类的构造函数体中的内容。
1#include <iostream>
2#include <string>
3using namespace std;
4
5class A {
6public:
7 A(string name) {cout << name << " ";}
8};
9
10class Base {
11public:
12 Base(string str) : a1(str) {}
13public:
14 A a1;
15};
16
17class Derived : public Base {
18public:
19 Derived() : a4("a4"), Base("a1"), a2("a2") {}
20public:
21 A a2;
22 A a3 = A("a3");
23 A a4;
24};
25
26int main()
27{
28 Derived d;
29 return 0;
30}
31// 输出:a1 a2 a3 a4
1#include <iostream>
2#include <string>
3using namespace std;
4
5class Base {
6public:
7 Base(int val) : a(val) {}
8protected:
9 int a;
10};
11
12class Derived : public Base {
13public:
14 Derived(int val1, int val2) : c(val2), Base(val1), b(a + c) {
15 cout << a << " " << b << " " << c << endl; // a==1, b的值不确定, c==10
16 }
17private:
18 int b;
19 int c;
20};
21
22int main()
23{
24 Derived d(1, 10);
25}