C++ Virtual Keyword and Confusion of a Reference Creation Expression

For the first week I started my job, I mainly review C++ apart from those administration matters. There are some tutorials inside company wiki. When I review the virtual feature of C++, my brain is a little bit of mess. Also, I meet a confusing expression related with reference. Therefore, after I figure out what happened exactly, I decide to write these things for a backup of my memory.

2023-07-23 Update

前段时间因为试着找国内的工作,看了下C++的面经,正好巩固了些基础知识。当然这十个月的工作中也学了一些C++。现在回过头来看当时的疑惑,其实也就是些基础知识,但是因为没有系统性学C++,所以那时候查起来也有困难。

现在也能给当时的疑惑一个简单的解答了。AClass& a(anotherObject),只不过是一种初始化方式,也就是下面的第二种,只不过是初始化一个reference而不是普通的variable:

1
2
3
int a = 1;
int a(1);
int a{1};

virtual关键字用来C++实现动态多态。derived class可以override在base class里使用了virtual关键字的方法。当使用base class的指针指向一个derived class的实例,就可以调用derived class里被override的方法了。

virtual特性的一种实现是(大多数编译器也是这么做的):每一个derived class要维护一个virtual table,virtual table里有指向virtual函数的指针。base class有一个virtual table pointer的属性,指向virtual table。到了调用virtual函数的时候,就从virtual table里找对应的函数指针。

至于virtual table pointer指向哪个地址,我没有深究,但是猜测是derived class在初始化的时候会给base class的virtual table pointer初始化值,指向自己的virtual table。

Conclusion

When not use virtual to try to override a method (getClassName) in the derived class, as case 2, the pointer p2base of parent class type (CMyClass) call the method from its own class, NOT the child's (CMyDerivedClass) method, although the pointer points to a child class object.

After add virtual keyword to the method, the p2base object pointer calls the child's method. As case 1, this behavior is intuitive as we expect.

Case 1: virtual keyword before the methods.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// the parent class
class CMyClass {

public:

// some methods

virtual string getClassName() {
return "CMyClass";
}

private:
// ...

}

// the child class
class CMyDerivedClass : public CMyClass {

public:

virtual string getClassName() {
return "CMyDerivedClass";
}

private:
// ...
}

int main()
{
CMyDerivedClass child;

CMyClass* p2base = &child;

cout << "get class name from parent pointer to child." << endl;
cout << p2base->getClassName() << endl;

CMyDerivedClass* pchild = &child;

CMyDerivedClass lv_Test3(*pchild);
CMyClass& lv_Test4(*pchild);
CMyClass lv_Test5(*pchild);

cout << "last tests" << endl;
cout << "lv_Test3: " << lv_Test3.getClassName() << endl;
cout << "lv_Test4: " << lv_Test4.getClassName() << endl;
cout << "lv_Test5: " << lv_Test5.getClassName() << endl;

}

The running result:

1
2
3
4
5
6
get class name from parent pointer to child.
CMyDerivedClass
last tests
lv_Test3: CMyDerivedClass
lv_Test4: CMyDerivedClass
lv_Test5: CMyClass

Case 2: no virtual keyword before the methods

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// the parent class
class CMyClass {

public:

// some methods

string getClassName() {
return "CMyClass";
}

private:
// ...

}

// the child class
class CMyDerivedClass : public CMyClass {

public:

string getClassName() {
return "CMyDerivedClass";
}

private:
// ...
}

The running result:

1
2
3
4
5
6
get class name from parent pointer to child.
CMyClass
last tests
lv_Test3: CMyDerivedClass
lv_Test4: CMyClass
lv_Test5: CMyClass

Confusion

I've been confuesd by the expression CMyClass& lv_Test4(*pchild); for two days. I searched lots of keywords, copy constructor, copy initialisation, reference initialisation, base class instantiation from devrived object ...

I thought it would be the same as first create an object of CMyClass and then create an reference to that object. Therefore, I tried the following code

1
2
3
4
5
CMyClass cp4Test6(child);
CMyClass& lv_Test6 = cp4Test6;

cout << "lv_Test4: " << lv_Test4.getClassName() << endl;
cout << "lv_Test6: " << lv_Test6.getClassName() << endl;

Suddenly I came up an idea to check the address of child and lv_Test4 in case 1. It found out that the addresses were the same.

Therefore, it just created a reference to child.

Virtual, Override

c++ - Should I use virtual, override, or both keywords? - Stack Overflow

Virtual keyword marks the method in the base class virtual, and the derived class can override the virtual method in the base class. While the derived class does not need to use virtual keyword before the overridden method. If used, it indicates the method can be further overridden in the further derived class.

The override keyword, only used in the derived class for the method override.